#!/usr/bin/env python
# encoding: utf-8

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtPrintSupport import QPrinter, QPrintDialog,QPrintPreviewDialog
from PIL import Image
import xlwt
import xlrd
import xlsxwriter

#  from PyQt5.QtChart import QChart,QChartView,QSplineSeries,QScatterSeries,QValueAxis
import PyQt5_stylesheets

from scipy.interpolate import spline
import scipy.signal as signal
from scipy import interpolate
import numpy as np
import pyqtgraph as pg
# from pyqtgraph import TreeWidget
import pyqtgraph.opengl as gl
from pyqtgraph.opengl import GLViewWidget
import pyqtgraph.exporters
# pg.setConfigOption(background='r')
from pyqtgraph import GraphicsLayoutWidget
# from dbsession import session,Oar,OarData,Pdd,PddData
# from dbsession import session,Condition,Data
from win32api import GetSystemMetrics
import random

import os
import re
import codecs
import time
import win32api
# from pykeyboard import PyKeyboard
import configparser
config = configparser.ConfigParser()
config_file = os.getcwd()+'/conf/config.ini'
config.read(config_file)
SKIN = config['base']['skin']
# from dbsession import session,Device,Condition,Data
#  from dbsession import SqlDeal

class tabViewTask(QTableView):
    def __init__(self, parent=None):
        '''表格初始化'''
        super(tabViewTask, self).__init__(parent)
        self.model = QStandardItemModel(0, 0)
        self.HeaderList = ['时间','路线','类型','能量','射线','射线步距','尺寸','边缘','边缘步距','深度','方向','源波距']
        self.model.setHorizontalHeaderLabels(self.HeaderList)#
        self.setModel(self.model)
        #下面代码让表格100填满窗口
        self.horizontalHeader().setStretchLastSection(True)
        self.clicked.connect(self.tabClicked)

        self.setMaximumHeight(250)

    def addOarTask(self,data):
        self.model.clear()
        self.model = QStandardItemModel(0, 0)
        self.HeaderList = ['时间','路线','类型','能量','射线','步距','尺寸','边缘距离','深度','方向','源波距']
        self.model.setHorizontalHeaderLabels(self.HeaderList)#
        self.setModel(self.model)
        for i in range(0,len(data)):
            #  del data[i][8]
            for j in range(0,len(data[i])):
                self.model.setItem(i, j, QStandardItem(str(data[i][j])))

    def addPddTask(self,data):
        self.model.clear()
        self.model = QStandardItemModel(0, 0)
        self.HeaderList = ['时间','路线','类型','能量','射线','尺寸','步距','深度','源波距']
        self.model.setHorizontalHeaderLabels(self.HeaderList)#
        self.setModel(self.model)
        for i in range(0,len(data)):
            for j in range(0,len(data[i])):
                self.model.setItem(i, j, QStandardItem(str(data[i][j])))

    def tabClicked(self,index):
        row = index.row()
        col  = self.model.columnCount()
        self.click_data = [self.model.data(self.model.index(row, i)) for i in range(0,col)]
        selections = self.selectionModel()
        selected = selections.selectedIndexes()
        # rows = [s.row() for s in selected]
        self.selected_data =list(set([self.model.data(self.model.index(r, 0)) for r in [s.row() for s in selected]]))

class tabView(QTableView):
    def __init__(self, parent=None):
        '''表格初始化'''
        super(tabView, self).__init__(parent)
        self.model = QStandardItemModel(0, 0)
        self.HeaderList = ['x(mm)','y(mm)','z(mm)','主测通道','监测通道','修正','归一化']
        self.model.setHorizontalHeaderLabels(self.HeaderList)#
        self.setModel(self.model)
        #下面代码让表格100填满窗口
        self.horizontalHeader().setStretchLastSection(True)
        self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.isClearChooseLine_Flag = False
        #  self.setMaximumHeight(250)

        self.clear_data()
        # 右键菜单设置
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.right_menu)

    def right_menu(self):
        self.menu = QMenu()
        exportAction = QAction("&导出excel",triggered=self.exportToExcel)
        self.menu.addAction(exportAction)
        self.menu.exec(QCursor.pos())

    def clear_data(self):
        self.model.clear()
        self.model = QStandardItemModel(0, 0)
        self.HeaderList = ['x(mm)','y(mm)','z(mm)','主测通道','监测通道','修正','归一化']
        # self.HeaderList = ['时间','深度','主测通道','监测通道','修正','归一化']
        self.model.setHorizontalHeaderLabels(self.HeaderList)#
        self.setModel(self.model)

    def add_data(self,x,y,z,t1,t2):
        rowNum = self.model.rowCount()  # 总行数
        t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        self.model.setItem(rowNum, 0, QStandardItem(str(t)))
        self.model.setItem(rowNum, 1, QStandardItem(str(x)))
        self.model.setItem(rowNum, 2, QStandardItem(str(y)))
        self.model.setItem(rowNum, 3, QStandardItem(str(z)))
        self.model.setItem(rowNum, 4, QStandardItem(str(t1)))
        self.model.setItem(rowNum, 5, QStandardItem(str(t2)))

    def exportToExcel(self):
        f = QFileDialog.getSaveFileName(self,"导出Excel",'%s/data'%os.getcwd(),'Excel Files(*.xls)')
        if f[0]:
            try:
                filename = f[0]
                wb = xlwt.Workbook()
                ws = wb.add_sheet('sheet1')#sheetname
                data = []
                data.append(self.HeaderList)
                row = self.model.rowCount()
                for r in range(0,row):
                    data.append([
                        float(self.model.data(self.model.index(r,0))),
                        float(self.model.data(self.model.index(r,1))),
                        float(self.model.data(self.model.index(r,2))),
                        float(self.model.data(self.model.index(r,3))),
                        float(self.model.data(self.model.index(r,4))),
                        float(self.model.data(self.model.index(r,5))),
                        float(self.model.data(self.model.index(r,6))),
                    ])
                for i in range(0,len(data)):
                    for j in range(0,len(data[i])):
                        ws.write(i, j, data[i][j])
                wb.save(filename)
                QMessageBox.warning(self,'提示','导出成功!\r\n%s'%filename,QMessageBox.Yes)
            except:
                QMessageBox.warning(self,'警告','文件被占用，无法导出!',QMessageBox.Yes)

    def exportToFile(self,task):
        '''计算pdd或oar重复性和归一化，
        并导出表格数据为.pdd文件或.oar文件'''
        t = task
        taskinfo = ''
        filename= ''
        row = self.model.rowCount()
        Tm = []
        Ts = []
        x = []
        y = []
        z = []
        for r in range(0,row):
            x.append(float(self.model.data(self.model.index(r,1))))
            y.append(float(self.model.data(self.model.index(r,2))))
            z.append(float(self.model.data(self.model.index(r,3))))
            Tm.append(float(self.model.data(self.model.index(r,4))))
            Ts.append(float(self.model.data(self.model.index(r,5))))
        #　计算重复性
        Repeat  = [float('%.4f'%(Tm[i]/(Ts[i]+0.00001))) for i in range(0,row)]
        #　计算归一化
        normal = None
        timetest = time.strftime("%Y:%m:%d-%H:%M:%S", time.localtime())
        if t['tasktype']== 'pdd':
            dR_max = max(Repeat)
            normal = [float('%.4f'%(Repeat[i]/dR_max)) for i in range(0,row)]
            taskinfo='测试类型:%s\r\n能量:%s\r\n射线:%s\r\nSSD:%s\r\n射野尺寸:%s\r\n深度:%s\r\n步距:%s\r\n\r\n坐标移动:%s-->%s'%(
                t['tasktype'],t['power'],t['rayType'],t['ssd'],t['raySize'],t['distance'],t['step'],t['directionAxis'][0],t['directionAxis'][1])
            filename = '%s__%s__%s__%s__.pdd'%(timetest,t['rayType'],t['power'],t['raySize'])
        if t['tasktype']== 'oar':
            dR_zero = Repeat[y.index(0)]
            normal = [float('%.4f'%(Repeat[i]/dR_zero)) for i in range(0,row)]
            taskinfo = '测试类型:%s\r\n能量:%s\r\n射线:%s\r\nSSD:%s\r\n测试深度:%s\r\n射野尺寸:%s\r\n射野步距:%s\r\n边缘距离:%s\r\n边缘步距:%s\r\n\r\n方向:%s\r\n坐标移动:%s-->%s'%(
                t['tasktype'],t['power'],t['rayType'],t['ssd'],t['deepth'],t['raySize'],t['rayStep'],t['edgeFiled'],t['edgeStep'],t['direction'],t['directionAxis'][0],t['directionAxis'][1])
            filename = '%s__%s__%s__%s__.oar'%(timetest,t['rayType'],t['power'],t['raySize'])
        for i in range(0,row):
            self.model.setItem(i, 6, QStandardItem(str(Repeat[i])))
            self.model.setItem(i, 7, QStandardItem(str(normal[i])))
        data = ''
        for r in range(0,row):
            t='%s,%s,%s,%s,%s,%s,%s,%s'%(
                self.model.data(self.model.index(r,0)),
                self.model.data(self.model.index(r,1)),
                self.model.data(self.model.index(r,2)),
                self.model.data(self.model.index(r,3)),
                self.model.data(self.model.index(r,4)),
                self.model.data(self.model.index(r,5)),
                self.model.data(self.model.index(r,6)),
                self.model.data(self.model.index(r,7)))
            data = data+t+'\r\n'
        timetest = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        inf =   '测试时间:%s\r\n'%timetest+\
                'Data Begin:\r\n\r\n'+\
                '数据个数:%s\r\n'%row+\
                'T,X,Y,Z,主测,监测,修正,归一化\r\n'+\
                '%s\r\n'%data+\
                'Data End\r\n'+\
                '\r\n%s\r\n'%taskinfo
        with open('pddoar/%s'%filename, 'w') as f:
            f.write(inf)

    def add_excel_data(self,data):
        self.clear_data()
        for j in range(0,len(data)):
            for i in range(0,len(data[j])):
                self.model.setItem(i, j, QStandardItem(str(data[j][i])))

    def addData(self,data):
        self.clear_data()
        for i in range(0,len(data)):
            for j in range(0,len(data[i])):
                self.model.setItem(j, i, QStandardItem(str(data[i][j])))

    def get_standard(self,x,ave):
        import math
        n = len(x)
        s = 0
        for i in range(0,n):
            s = s+pow((int(x[i])-ave),2)
        s = math.sqrt(1/(n-1)*s)
        return s

    def get_data(self):
        rowNum = self.model.rowCount()  # 总行数
        x = [self.model.data(self.model.index(i, 1)) for i in range(0,rowNum)]
        line1 = [self.model.data(self.model.index(i, 4)) for i in range(0,rowNum)]
        line2 = [self.model.data(self.model.index(i, 5)) for i in range(0,rowNum)]
        return (x,line1,line2)

    def get_all_data(self):
        rowNum = self.model.rowCount()  # 总行数
        colNum = self.model.columnCount()  # 总行数
        data = []
        for j in range(0,colNum):
            col = [self.model.data(self.model.index(i, j)) for i in range(0,rowNum)]
            data.append(col)
        return data

class AnalyseGlWidget(GLViewWidget):
    def __init__(self):
        super(AnalyseGlWidget, self).__init__()
        self.opts['distance'] = 40
        self.gx = gl.GLGridItem()
        self.gx.rotate(90, 0, 1, 0)
        self.gx.translate(-10, 0, 0)
        self.addItem(self.gx)
        self.gy = gl.GLGridItem()
        self.gy.rotate(90, 1, 0, 0)
        self.gy.translate(0, -10, 0)
        self.addItem(self.gy)
        self.gz = gl.GLGridItem()
        self.gz.translate(0, 0, -10)
        self.addItem(self.gz)
        self.setScale(40,40,100)
        self.drawDirectionLine()
        self.title = '平面扫描结果显示'

    def setScale(self, size_x, size_y, size_z):
        # axis range ---> x,y,z
        self.x_min = -20
        self.x_max = 20
        self.y_min = -20
        self.y_max = 20
        self.z_min = -20
        self.z_max = 20
        # set real range
        self.x_range = size_x
        self.y_range = size_y
        self.z_range = size_z
        # get transform scale
        self.x_scale = (self.x_max-self.x_min)/self.x_range
        self.y_scale = (self.y_max-self.y_min)/self.y_range
        self.z_scale = (self.z_max-self.z_min)/self.z_range

    def drawDirectionLine(self):
        # draw direction A->B
        self.vLine = gl.GLLinePlotItem(pos=np.array([[self.x_min/2,0,self.z_min/2],[self.x_max/2,0,self.z_min/2]]), color=pg.glColor(0,250,255), width=1, antialias=True)
        self.addItem(self.vLine)
        # draw direction G->T
        self.hLine = gl.GLLinePlotItem(pos=np.array([[0,self.y_min/2,self.z_min/2],[0,self.y_max/2,self.z_min/2]]), color=pg.glColor(250,0,255), width=1, antialias=True)
        self.addItem(self.hLine)
        # draw direction Z
        self.zLine = gl.GLLinePlotItem(pos=np.array([[0,self.y_min/2,self.z_min/2],[0,self.y_min/2,self.z_max/2]]), color=pg.glColor(250,0,55), width=1, antialias=True)
        self.addItem(self.zLine)

    def paintGL(self, *args, **kwds):
        GLViewWidget.paintGL(self, *args, **kwds)
        self.qglColor(Qt.white)
        for i in range(self.x_min,self.x_max+1):
            if i%2 == 0:
                # x axis
                self.renderText(i/2, self.y_max/2+2, self.z_min/2, str(int(i/self.x_scale)))
                # y axis
                self.renderText(self.x_max/2+2, i/2, self.z_min/2, str(int(i/self.y_scale)))
                # z axis
                self.renderText(self.x_min/2, self.y_max/2+1, i/2, str(int(i/self.z_scale)+self.z_range/2))
        self.renderText(0, 0, self.z_max/2+5, self.title)
        self.qglColor(Qt.blue)
        self.renderText(self.x_min/2, self.y_max/2, 12, 'Dose Rate(%)')
        self.renderText(0, self.y_max/2+5, self.z_min/2, 'x(mm)')
        self.renderText(self.x_max/2+5, 0, self.z_min/2, 'y(mm)')
        self.qglColor(Qt.green)
        self.renderText(self.x_min/2, 0, self.z_min/2, 'A')
        self.renderText(self.x_max/2, 0, self.z_min/2, 'B')
        self.renderText(0, self.y_min/2, self.z_min/2, 'G')
        self.renderText(0, self.y_max/2, self.z_min/2, 'T')

    def axisToGL(self,x,y,z):
        x = [t*self.x_scale/2 for t in x]
        y = [t*self.y_scale/2 for t in y]
        z = [t*self.z_scale/2-self.z_max/2 for t in z]
        return x,y,z

    def updateSurface(self, x, y, z, size):
        s = float(re.search(r'([0-9]+)',size).group(0))
        self.setScale(int(s)*10*2,int(s)*10*2,100)
        x,y,z = self.axisToGL(x,y,z)
        pos = np.array([[a,b,c] for a,b,c in zip(x,y,z)])
        pos = np.empty((len(z),3))
        size = np.empty((len(z)))
        color = np.empty((len(z), 4))
        for i in range(len(z)):
            pos[i] = (x[i],y[i],z[i])
            size[i] = 0.1
            color[i] = (1.0, 0.0, 0.0, 0.7)
        x = np.array(sorted(set(x)))
        y = np.array(sorted(set(y)))
        z = np.array(z)
        z = z.reshape(np.size(x),np.size(y))
        self.items = []
        self.addItem(self.gx)
        self.addItem(self.gy)
        self.addItem(self.gz)
        self.addItem(self.hLine)
        self.addItem(self.vLine)
        self.addItem(self.zLine)
        p = gl.GLSurfacePlotItem(x=x,y=y,z=z, shader='shaded', color=(0.5, 0.5, 1, 0.7))
        self.addItem(p)
        sp = gl.GLScatterPlotItem(pos=pos, size=size, color=color, pxMode=False)
        self.addItem(sp)

    def drawLine(self,x,y,z,size):
        s = float(re.search(r'([0-9]+)',size).group(0))
        self.setScale(int(s)*10*2,int(s)*10*2,100)
        x = np.array(x)*self.x_scale/2
        y = np.array(y)*self.y_scale/2
        z = np.array(z)*self.z_scale/2-self.z_max/2
        self.items = []
        self.addItem(self.gx)
        self.addItem(self.gy)
        self.addItem(self.gz)
        self.addItem(self.hLine)
        self.addItem(self.vLine)
        self.addItem(self.zLine)
        pts = [[a,b,c] for a,b,c in zip(x,y,z)]
        plt = gl.GLLinePlotItem(pos=np.array(pts), color=pg.glColor((1,1.3)), width=(8)/10., antialias=True)
        self.addItem(plt)

class GraphWindow(GraphicsLayoutWidget):
    def __init__(self):
        super(GraphWindow, self).__init__()
        font=QFont()
        font.setBold(True)
        font.setPixelSize(15)
        self.label = pg.LabelItem(justify='right')
        self.label.setFont(font)
        self.addItem(self.label,0,1,colspan=1)
        self.tunnelLine = self.addPlot(1,1,colspan=2)

        self.tunnelLine.getAxis("bottom").tickFont = font
        self.tunnelLine.getAxis("left").tickFont = font
        self.scatter = pg.ScatterPlotItem(size=12, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 5, 180))
        self.scatter.setData([0],[0])
        # self.scatter_2 = pg.ScatterPlotItem(size=10, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 180))
        # self.scatter_2.setData([0],[0])
        # self.tunnelLine.addItem(self.scatter_1)
        self.tunnelLine.addItem(self.scatter)
        # self.tunnelLine.set_xlabel()
        #  self.removeItem()
        self.tunnelLine.setAutoVisible(y=True)
        self.tunnelLine.setTitle('曲线')
        self.data_x = np.array([1,2,3,4,5,6,7,8,9,10])
        self.data_y = np.array([0,5,2,3,3,5,6,7,8,9])

        #  self.curve_master = self.tunnelLine.plot([-100,100],[50,50],pen='r',name='曲线')
        self.data = np.random.normal(size=10)
        # self.curve_zero = self.tunnelLine.plot([0,0],[0,120],pen='w',name='零点位置')
        self.curve= self.tunnelLine.plot([0,0],[0,0],pen=pg.mkPen('b', width=3),name='原始数据曲线')
        self.curve_deal= self.tunnelLine.plot([0,0],[0,0],pen=pg.mkPen('r', width=3),name='数据处理曲线')

        self.curve_left_1 = self.tunnelLine.plot([0],[0], pen=(0,200,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=8, name="symbol='o'")
        self.curve_left_2 = self.tunnelLine.plot([0],[0], pen=(0,200,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=8, name="symbol='o'")
        self.curve_right_1 = self.tunnelLine.plot([0],[0], pen=(0,200,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=8, name="symbol='o'")
        self.curve_right_2 = self.tunnelLine.plot([0],[0], pen=(0,200,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=8, name="symbol='o'")

        self.legends = pg.LegendItem()
        self.legends.setParentItem(self.tunnelLine)
        # self.legends.addItem(self.curve_zero,'零点位置')
        # self.legends.addItem(self.curve,'原始曲线')
        # self.legends.addItem(self.curve_deal,'处理曲线')

        self.text = pg.TextItem(html='<div style="text-align: center"><span style="color: #FF0;">information</span><br><span style="color: #FFF; font-size: 26pt;">PEAK</span></div>', anchor=(-0.3,0.5), angle=0, border='w', fill=(0, 0, 255, 100))
        self.tunnelLine.addItem(self.text)
        self.text.setPos(200,100)


        self.colorlist = [
            (0,128,64),
            (0,0,255),
            (0,0,160),
            (128,0,128),
            (128,0,255),
            (255,128,0),
            (255,128,128),
            (255,128,255),
            (255,128,192),
            (128,0,0), ]

        #鼠标十字移动
        self.vLine = pg.InfiniteLine(pen=pg.mkPen('b', width=1),angle=90, movable=False)
        self.hLine = pg.InfiniteLine(pen=pg.mkPen('b', width=1),angle=0, movable=False)
        self.tunnelLine.addItem(self.vLine, ignoreBounds=True)
        self.tunnelLine.addItem(self.hLine, ignoreBounds=True)
        #鼠标移动绑定
        self.vb = self.tunnelLine.vb
        self.proxy = pg.SignalProxy(self.tunnelLine.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)
        # 鼠标坐标显示文本
        self.text_pos = pg.TextItem("(0,0)", anchor=(0.5, -1.0),color='b')
        self.tunnelLine.addItem(self.text_pos)
        self.text_pos.setPos(0,0)
        # 网格显示
        self.tunnelLine.showGrid(x = True, y = True, alpha = 0.7)
        # 坐标显示
        self.tunnelLine.setLabel('left', "相对剂量(%)", units='')
        self.tunnelLine.setLabel('bottom', "距离(mm)", units='')

        self.pdd_result = {}
        self.oar_result = {}
        self.ebeam_result = {}
        # exporter = pg.exporters.ImageExporter(self.tunnelLine)
        # exporter.parameters()['width'] = 100   # (note this also affects height parameter)
        # # save to file
        # exporter.export('fileName.png')

    def update(self):
        self.data[:-1] = self.data[1:]  # shift data in the array one sample left
                                # (see also: np.roll)
        self.data[-1] = np.random.normal()

    def updateRegion(self, window, viewRange):
        rgn = viewRange[0]
        self.region.setRegion(rgn)

    def mouseMoved(self, evt):
        pos = evt[0]  ## using signal proxy turns original arguments into a tuple
        if self.tunnelLine.sceneBoundingRect().contains(pos):
            mousePoint = self.vb.mapSceneToView(pos)
            index = mousePoint.x()
            # self.tunnelLine.setLabel('bottom', "距离(mm)\t\t\t\tx=%s"%mousePoint.x(), units='')
            self.setCursor(Qt.BlankCursor)
            self.vLine.setPos(mousePoint.x())
            self.hLine.setPos(mousePoint.y())
            self.text_pos.setText("(%0.1f,%0.1f)"%(mousePoint.x(),mousePoint.y()))
            self.text_pos.setPos(mousePoint.x(),mousePoint.y())

    def smooth(self,x,y):
        '''曲线平滑: 细分x轴为0.1为最小刻度，通过tck拟合函数进行曲线拟合 '''
        # tck = interpolate.splrep(x, y)
        # xnew = np.arange(x.min(),x.max(),0.1)
        # ynew = interpolate.splev(xnew, tck)

        # ynew = spline(x,y,xnew)
        # func = interpolate.interp1d(x, y, kind='cubi')
        # 利用xnew和func函数生成ynew，xnew的数量等于ynew数量
        xnew = np.arange(x.min(),x.max(),0.1)
        func = interpolate.interp1d(x, y, kind='linear')
        ynew = func(xnew)

        # tck = interpolate.splrep(x, y)
        # xnew = np.arange(x.min(),x.max(),0.1)
        # ynew = interpolate.splev(xnew, tck)
        return xnew,ynew

    def aveFilter(self,y,span):
        '''均值滤波
        span = 5:
        y(1) = y(1)
        y(2) = y(1)+y(2)+y(3)/3
        y(3) = y(1)+y(2)+y(3)+y(4)+y(5)/5
        '''
        # span = 7
        s = 0
        cen = int(span/2)
        for i in range(0,len(y)):
            if i >= cen:
                y_t = y[i-cen:i+cen]
                if len(y)-i<=cen:
                    y[i]= y[i]
                else:
                    y[i]= sum(y_t)/len(y_t)
            elif 0<i<cen :
                s = s+2
                y_t = y[0:s+1]
                y[i]= sum(y_t)/len(y_t)
        return y

    def linearInterpolation(self, x,y,rate):
        '''插值法计算'''
        for i in range(1, len(y)):
            if y[i-1] < rate < y[i] or y[i-1] > rate > y[i]:
                k = (y[i] - y[i-1])/(x[i] - x[i-1])
                b = y[i] - k*x[i]
                x_r = (rate - b)/k
                return x_r
        return False

    def find_nearest(self,array,value):
        # idx = (np.abs(array-value)).argmin()
        # return array[idx]
        err = [abs(a-value) for a in array]
        index = err.index(min(err))
        return index

    def getEbeamPdd(self,x,y,raySize):
        '''电子束-pdd测量结果显示

        x: 坐标系x值(O->G方向上的走位坐标)
        y: 坐标位置对应测量剂量率

        计算结果：
            R100: 100%剂量率位置
            R80: 80%剂量率位置
            R50: 50%剂量率位置
            E0: 能量
            RP:
        '''
        R100 = x[y.index(max(y))]
        R80 = self.linearInterpolation(x,y,80)
        R50 = self.linearInterpolation(x,y,50)
        E0 = 2.33*R50/10
        # 计算RP
        L_E0 = [1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,50]
        L_RP = [0.505,1.01,1.51,2.02,2.52,3.02,3.52,4.02,4.52,5.02,5.91,6.90,7.89,8.88,9.87,12.3,14.8,19.6,24.6]
        RP = self.linearInterpolation(L_RP,L_E0,E0)
        html = """ <div style="text-align: center">
                    <span style="color: #000000;font-size: 12pt;">R100:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2fmm</span>
                    <br>
                    <span style="color: #000000;font-size: 12pt;">R80:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2fmm</span>
                    <br>
                    <span style="color: #000000;font-size: 12pt;">R50:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2fmm</span>
                    <br>
                    <span style="color: #000000;font-size: 12pt;">E0:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2fMev</span>
                    <br>
                    <span style="color: #000000;font-size: 12pt;">Rp:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2fmm</span>
                    <br>
                   </div>
                """%(R100,R80,R50,E0,RP)
        self.ebeam_result = {
            "R100":R100,
            "R80":R80,
            "R50":R50,
            "E0":E0,
            "RP":RP,
            "x":x,
            "y":y,
        }
        # 清空曲线重新绘制
        self.tunnelLine.clear()
        curve= self.tunnelLine.plot(x,y,pen=pg.mkPen('b', width=3),name='原始数据曲线')
        curve_deal= self.tunnelLine.plot(x,y,pen=pg.mkPen('r', width=3),name='数据处理曲线')

        # 最大值
        y_max = max(y)
        x_max = x[y.index(y_max)]
        arrow = pg.ArrowItem(pos=(x_max, y_max), angle=-30)
        text_max = pg.TextItem(html='<div style="text-align: center"><span style="color: #000; font-size: 8pt;">Max(%s,%s)</span></div>'%(x_max,y_max), anchor=(-0.3,0.5), angle=30, border='w', fill=(0, 0, 255, 100))
        text_max.setPos(x_max, y_max)
        self.tunnelLine.addItem(arrow)
        self.tunnelLine.addItem(text_max)
        s1 = pg.ScatterPlotItem([x_max],[y_max],size=10, pen=pg.mkPen(None), brush=pg.mkBrush(0, 0, 250, 250))
        self.tunnelLine.addItem(s1)

        self.text.setHtml(html)
        self.text.setPos(max(x)*2/3,max(y)*2/3)
        self.tunnelLine.addItem(self.vLine, ignoreBounds=True)
        self.tunnelLine.addItem(self.hLine, ignoreBounds=True)
        self.tunnelLine.addItem(self.text_pos)
        self.tunnelLine.addItem(self.text)
        self.tunnelLine.setLimits(xMin=min(x),xMax=max(x)+10,yMin=0,yMax=max(y)+20)
        self.tunnelLine.autoRange()

    def getEbeamOar(self,x,y,raySize):
        '''电子束-平坦度测量结果显示

        x: 走位坐标
        y: 对应坐标的百分比剂量率
        raySize: 射野大小

        return：
            设定条件：射野: 10cm*10cm，源皮距: 100cm, 测量深度：最大剂量点位置
            uniform(均整性)：在x,y轴上90%剂量率区域与射野边缘之间的距离不大于10mm,两边计算出来后,取最大间隔
            symmetry(对称性)：在90%区域再内推1cm的区域中最大剂量率与最小剂量率的比值
        '''
        # 左半边x,y
        x_left = x[0:int(len(x)/2)]
        y_left = y[0:int(len(y)/2)]
        # 右半边x,y
        x_right = x[int(len(x)/2):]
        y_right = y[int(len(y)/2):]
        # 左边接近90点的位置
        x_left_90 = self.linearInterpolation(x_left,y_left,90)
        # 右边接近90点的位置
        x_right_90 = self.linearInterpolation(x_right,y_right,90)
        # 射野大小
        visualField = float(re.search(r'([0-9]+)',raySize).group(0))
        # 均整区与射野左边距离
        uniformArea_left_interval =abs(visualField*10/2-abs(x_left_90))
        # 均整区与射野右边距离
        uniformArea_right_interval = abs(visualField*10/2-abs(x_right_90))
        uniform = 0
        if uniformArea_left_interval>uniformArea_right_interval:
            uniform = uniformArea_left_interval
        else:
            uniform = uniformArea_right_interval
        # 对称区域，90%内推1cm
        symmetryArea = []
        if x_left_90 > 0 and x_right_90 < 0:
            n_xl = self.find_nearest(x_left,x_left_90-10)
            n_xr = self.find_nearest(x_right,x_right_90+10)
            symmetryArea_left = [ y for y in y_left[n_xl:]]
            symmetryArea_right = [ y for y in y_right[:n_xr]]
            for l,r in zip(symmetryArea_left,symmetryArea_right):
                symmetryArea.append(l)
                symmetryArea.append(r)
        if x_left_90 < 0 and x_right_90 > 0:
            n_xl = self.find_nearest(x_left,x_left_90+10)
            n_xr = self.find_nearest(x_right,x_right_90-10)
            symmetryArea_left = [ y for y in y_left[n_xl:]]
            symmetryArea_right = [ y for y in y_right[:n_xr]]
            for l,r in zip(symmetryArea_left,symmetryArea_right):
                symmetryArea.append(l)
                symmetryArea.append(r)
        symmetry = max(symmetryArea)/min(symmetryArea)
        # 曲线显示
        html = """ <div style="text-align: center">
                    <span style="color: #000000;font-size: 12pt;">均整度(max):</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2f</span>
                    <br>
                    <span style="color: #000000;font-size: 12pt;">对称性:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2f%%</span>
                    <br>
                   </div>
                """%(uniform,symmetry)
        self.oar_result = {
            "x":x,
            "y":y,
            "uniform":uniform,
            "symmetry":symmetry*100,
        }
        # 清空曲线重新绘制
        self.tunnelLine.clear()
        # self.legends.clear() # 这里需要修改源码,方可使用clear()
        curve= self.tunnelLine.plot(x,y,pen=pg.mkPen('b', width=3),name='原始数据曲线')
        curve_deal= self.tunnelLine.plot(x,y,pen=pg.mkPen('r', width=3),name='数据处理曲线')
        curve_left_1 = self.tunnelLine.plot([x_left_90,x_left_90,x_left_90],[0,90,100], pen=(0,200,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=8, name="symbol='o'")
        curve_right_1 = self.tunnelLine.plot([x_right_90,x_right_90,x_right_90],[0,90,100], pen=(0,200,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=8, name="symbol='o'")
        # 最大值
        y_max = max(symmetryArea)
        x_max = x[y.index(y_max)]
        arrow = pg.ArrowItem(pos=(x_max, y_max), angle=-30)
        text_max = pg.TextItem(html='<div style="text-align: center"><span style="color: #000; font-size: 8pt;">Max(%s,%s)</span></div>'%(x_max,y_max), anchor=(-0.3,0.5), angle=30, border='w', fill=(0, 0, 255, 100))
        text_max.setPos(x_max, y_max)
        self.tunnelLine.addItem(arrow)
        self.tunnelLine.addItem(text_max)
        # 最小值
        y_min = min(symmetryArea)
        x_min = x[y.index(y_min)]
        arrow = pg.ArrowItem(pos=(x_min, y_min), angle=30)
        text_min = pg.TextItem(html='<div style="text-align: center"><span style="color: #000; font-size: 8pt;">Min(%s,%s)</span></div>'%(x_min,y_min), anchor=(-0.3,0.5), angle=-30, border='w', fill=(0, 0, 255, 100))
        text_min.setPos(x_min, y_min)
        self.tunnelLine.addItem(arrow)
        self.tunnelLine.addItem(text_min)
        # 最大、小值点
        s1 = pg.ScatterPlotItem([x_min,x_max],[y_min,y_max],size=10, pen=pg.mkPen(None), brush=pg.mkBrush(0, 0, 250, 250))
        self.tunnelLine.addItem(s1)
        # 文本
        self.text.setHtml(html)
        self.text.setPos(-20,20)
        self.tunnelLine.addItem(self.vLine, ignoreBounds=True)
        self.tunnelLine.addItem(self.hLine, ignoreBounds=True)
        self.tunnelLine.addItem(self.text_pos)
        self.tunnelLine.addItem(self.text)
        self.tunnelLine.setLimits(xMin=min(x)-10,xMax=max(x)+10,yMin=0,yMax=max(y)+20)
        self.tunnelLine.autoRange()

    def getPhotonPdd(self,x,y,raySize):
        ''' 光子-pdd测量结果显示

        x: 坐标系x值(O->G方向上的走位坐标)
        y: 坐标位置对应测量剂量率

        计算结果：
            R100: 100%剂量率位置
            R80: 80%剂量率位置
            R50: 50%剂量率位置
            D0: 0mm深度处剂量率
            D100: 100mm深度处剂量率
            D200: 200mm深度处剂量率
            D200/D100: 200mm深度处剂量率/100mm深度处剂量率
            Enery: 能量
            TPR:
        '''
        max_pos = y.index(max(y))
        x_r = x[max_pos:]
        y_r = y[max_pos:]
        R100 = x[max_pos]
        R80 = self.linearInterpolation(x_r,y_r,80)
        R50 = self.linearInterpolation(x_r,y_r,50)
        D200 = y[x.index(200.0)]
        D100 = y[x.index(100.0)]
        D0 = y[x.index(0.0)]
        # D20/D10、TPR计算
        D = D200/(D100)
        TPR = 2.189-1.308*(1/D)+0.249*(1/D)*(1/D)
        # 线性差值计算 y = k*x + b
        en = [4,6,8,10,14,16,22,30,50]
        D_list  = np.array([0.54,0.58,0.61,0.63,0.65,0.66,0.68,0.69,0.71])
        energy = self.linearInterpolation(en,D_list,D)

        # 曲线显示
        html = """ <div style="text-align: center">
                    <span style="font-size: 12pt;color: #000000;">D0:</span>
                    <span style="font-size: 12pt;color: #000000;text-align:right">%.2f %%</span>
                    <br>
                    <span style="font-size: 12pt;color: #000000;">D10:</span>
                    <span style="font-size: 12pt;color: #000000;text-align:right">%.2f %%</span>
                    <br>
                    <span style="font-size: 12pt;color: #000000;">D20:</span>
                    <span style="font-size: 12pt;color: #000000;text-align:right">%.2f %%</span>
                    <br>
                    <span style="font-size: 12pt;color: #000000;">D20/D10:</span>
                    <span style="font-size: 12pt;color: #000000;text-align:right">%.2f</span>
                    <br>
                    <span style="font-size: 12pt;color: #000000;">TPR20/10:</span>
                    <span style="font-size: 12pt;color: #000000;text-align:right">%.2f</span>
                    <br>
                    <span style="font-size: 12pt;color: #000000;">R_max:</span>
                    <span style="font-size: 12pt;color: #000000;text-align:right">%.2fmm</span>
                    <br>
                    <span style="font-size: 12pt;color: #000000;">R_80:</span>
                    <span style="font-size: 12pt;color: #000000;text-align:right">%.2fmm</span>
                    <br>
                    <span style="font-size: 12pt;color: #000000;">R_50:</span>
                    <span style="font-size: 12pt;color: #000000;text-align:right">%.2fmm</span>
                    <br>
                    <span style="font-size: 12pt;color: #000000;">Energy:</span>
                    <span style="font-size: 12pt;color: #000000;text-align:right">%.2fMeV</span>
                    <br>
                   </div>
                """%(D0,D100,D200,D,TPR,R100,R80,R50,energy)
        self.pdd_result = {
            "D0":D0,
            "D10":D100,
            "D20":D200,
            "D20_D10":D,
            "TPR":TPR,
            "R100":R100,
            "R80":R80,
            "R50":R50,
            "energy":energy,
            "x":x,
            "y":y,
        }
        # 清空曲线重新绘制
        self.tunnelLine.clear()
        curve= self.tunnelLine.plot(x,y,pen=pg.mkPen('b', width=3),name='原始数据曲线')
        curve_deal= self.tunnelLine.plot(x,y,pen=pg.mkPen('r', width=3),name='数据处理曲线')

        # 最大值
        y_max = max(y)
        x_max = x[y.index(y_max)]
        arrow = pg.ArrowItem(pos=(x_max, y_max), angle=-30)
        text_max = pg.TextItem(html='<div style="text-align: center"><span style="color: #000; font-size: 8pt;">Max(%s,%s)</span></div>'%(x_max,y_max), anchor=(-0.3,0.5), angle=30, border='w', fill=(0, 0, 255, 100))
        text_max.setPos(x_max, y_max)
        self.tunnelLine.addItem(arrow)
        self.tunnelLine.addItem(text_max)
        s1 = pg.ScatterPlotItem([x_max],[y_max],size=10, pen=pg.mkPen(None), brush=pg.mkBrush(0, 0, 250, 250))
        self.tunnelLine.addItem(s1)

        self.text.setHtml(html)
        self.text.setPos(max(x)*2/3,max(y)*2/3)
        self.tunnelLine.addItem(self.text)
        self.tunnelLine.addItem(self.text_pos)
        self.tunnelLine.addItem(self.vLine, ignoreBounds=True)
        self.tunnelLine.addItem(self.hLine, ignoreBounds=True)
        self.tunnelLine.setLimits(xMin=min(x),xMax=max(x)+10,yMin=0,yMax=max(y)+20)
        self.tunnelLine.autoRange()

    def getPhotonOar(self,x,y,raySize):
        """光子-平坦度测量

        计算：
            左边阴影:
            右边阴影:
            均整度:
            射野偏移:

        """
        # 左半边x,y
        x_l = x[0:int(len(x)/2)]
        y_l = y[0:int(len(y)/2)]
        # 右半边x,y
        x_r = x[int(len(x)/2):]
        y_r = y[int(len(y)/2):]
        # 左边最接近20的y的值
        x_l_R20 = self.linearInterpolation(x_l,y_l,20)
        x_l_R50 = self.linearInterpolation(x_l,y_l,50)
        x_l_R80 = self.linearInterpolation(x_l,y_l,80)
        # 右边最接近20的y的值
        x_r_R20 = self.linearInterpolation(x_r,y_r,20)
        x_r_R50 = self.linearInterpolation(x_r,y_r,50)
        x_r_R80 = self.linearInterpolation(x_r,y_r,80)
        # 射野偏移
        # visualField = float(raySize.replace('\n','').split('cm')[0])
        visualField = float(re.search(r'([0-9]+)',raySize).group(0))
        Field_50 = abs(x_r_R50)+abs(x_l_R50)
        halfField = 10*visualField/2
        Dev = (abs(abs(x_r_R50)-halfField)+abs(abs(x_l_R50)-halfField))/2
        dm = 0 # 单位cm
        if 5<=visualField<=10:
            dm = 1
        if 10<visualField<=30:
            dm = 0.1*visualField
        if 30<visualField:
            dm = 3
        # 均整区计算
        visual_xl = -(visualField*10/2-dm*10)
        visual_xr = (visualField*10/2-dm*10)
        err_l = [abs(x_-visual_xl) for x_ in x]
        err_r = [abs(x_-visual_xr) for x_ in x]
        n_l = (err_l.index(min(err_l)))
        n_r = (err_r.index(min(err_r)))
        if n_l<n_r:
            uniformArea = y[n_l:n_r]
        else:
            uniformArea = y[n_r:n_l]
        # 求出均整性(两边视野区域内，最大剂量/最小计量)
        Dmax = max(uniformArea)
        Dmin = min(uniformArea)
        flatValue = Dmax/Dmin
        # 均整区对称性
        symmetry = []
        lenth = len(uniformArea)
        for i in range(0,int(lenth/2)):
            l = uniformArea[i]
            r = uniformArea[lenth-1-i]
            if l<r:
                symmetry.append(r/l)
            else:
                symmetry.append(l/r)
        # 左边阴影
        left_shadow = abs(x_l_R20-x_l_R80)
        # 右边阴影
        right_shadow = abs(x_r_R20-x_r_R80)
        if symmetry:
            sym= max(symmetry)
        else:
            sym= 0
        html = """ <div style="text-align: center">
                    <span style="color: #000000; font-size: 12pt;">光射野重合性:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.1fmm</span>
                    <br>
                    <span style="color: #000000;font-size: 12pt;">均整度:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2f</span>
                    <br>
                    <span style="color: #000000;font-size: 12pt;">对称性:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2f%%</span>
                    <br>
                    <span style="color: #000000;font-size: 12pt;">Dmin:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2f%%</span>
                    <br>
                    <span style="color: #000000;font-size: 12pt;">左半影:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2fmm</span>
                    <br>
                    <span style="color: #000000;font-size: 12pt;">右半影:</span>
                    <span style="color: #000000;font-size: 12pt;text-align:right">%.2fmm</span>
                    <br>
                   </div>
                """%(Dev,flatValue,sym*100,Dmin,left_shadow,right_shadow)
        self.oar_result = {
            "Dev":Dev,
            "flatValue":flatValue,
            "sym":sym*100,
            "Dmin":Dmin,
            "left_shadow":left_shadow,
            "right_shadow":right_shadow,
            "x":x,
            "y":y,
        }
        # 清空曲线重新绘制
        self.tunnelLine.clear()
        curve_left_1 = self.tunnelLine.plot([x_l_R20,x_l_R20,x_l_R20],[0,20,100], pen=(0,200,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=8, name="symbol='o'")
        curve_left_2 = self.tunnelLine.plot([x_l_R80,x_l_R80,x_l_R80],[0,80,100], pen=(0,200,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=8, name="symbol='o'")
        curve_right_1= self.tunnelLine.plot([x_r_R20,x_r_R20,x_r_R20],[0,20,100], pen=(0,200,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=8, name="symbol='o'")
        curve_right_2= self.tunnelLine.plot([x_r_R80,x_r_R80,x_r_R80],[0,80,100], pen=(0,200,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=8, name="symbol='o'")
        curve= self.tunnelLine.plot(x,y,pen=pg.mkPen('b', width=3),name='原始数据曲线')
        curve_deal= self.tunnelLine.plot(x,y,pen=pg.mkPen('r', width=3),name='数据处理曲线')

        # 最大值
        x_max = x[y.index(Dmax)]
        arrow = pg.ArrowItem(pos=(x_max, Dmax), angle=-30)
        text_max = pg.TextItem(html='<div style="text-align: center"><span style="color: #000; font-size: 8pt;">Max(%s,%s)</span></div>'%(x_max,Dmax), anchor=(-0.3,0.5), angle=30, border='w', fill=(0, 0, 255, 100))
        text_max.setPos(x_max, Dmax)
        self.tunnelLine.addItem(arrow)
        self.tunnelLine.addItem(text_max)
        # 最小值
        x_min = x[y.index(Dmin)]
        arrow = pg.ArrowItem(pos=(x_min, Dmin), angle=30)
        text_min = pg.TextItem(html='<div style="text-align: center"><span style="color: #000; font-size: 8pt;">Min(%s,%s)</span></div>'%(x_min,Dmin), anchor=(-0.3,0.5), angle=-30, border='w', fill=(0, 0, 255, 100))
        text_min.setPos(x_min, Dmin)
        self.tunnelLine.addItem(arrow)
        self.tunnelLine.addItem(text_min)
        # 最大、小值点
        s1 = pg.ScatterPlotItem([x_min,x_max],[Dmin,Dmax],size=10, pen=pg.mkPen(None), brush=pg.mkBrush(0, 0, 250, 250))
        self.tunnelLine.addItem(s1)

        self.text.setHtml(html)
        self.text.setPos(-20,20)
        self.tunnelLine.addItem(self.vLine, ignoreBounds=True)
        self.tunnelLine.addItem(self.hLine, ignoreBounds=True)
        self.tunnelLine.addItem(self.text_pos)
        self.tunnelLine.addItem(self.text)
        self.tunnelLine.setLimits(xMin=min(x)-10,xMax=max(x)+10,yMin=0,yMax=max(y)+20)
        self.tunnelLine.autoRange()

    def pddPlotHistory(self,x,y,raySize,testType,rayType):
        'pdd曲线显示'
        if x and y:
            x = np.array(x)
            y = np.array(y)
            xnew = x
            ynew = y
            self.tunnelLine.setXRange(x.min(),x.max())
            self.tunnelLine.setYRange(y.min(),y.max())
            self.datax = xnew
            self.datay = ynew
            self.curve_master.setData(xnew,ynew)
            try:
                D,y100_position,y80_position,y50_position = self.getPdd(xnew,ynew)
                html = self.pddHtml(D,y100_position,y80_position,y50_position,testType,rayType,raySize)
                self.text.setHtml(html)
                self.text.setPos(0,y.max()/3)
            except:
                pass

    def multiLine(self,x,y,c):
        '''多条曲线显示'''
        self.tunnelLine.clear()
        self.legends.clear() # 这里需要修改源码,方可使用clear()
        curve_zero = self.tunnelLine.plot([0,0],[0,120],pen='w',name='零点位置')
        self.legends.addItem(curve_zero,'零点位置')
        for i in range(0,len(x)):
            curve= self.tunnelLine.plot(x[i],y[i],pen=self.colorlist[random.randint(0,9)])
            self.legends.addItem(curve,c[i])
        return

class DataDialog(QDialog):
    def __init__(self,parent=None):
        super(QDialog, self).__init__(parent)
        w = GetSystemMetrics (0)
        h = GetSystemMetrics (1)
        self.setMinimumSize(w/1.5,h/1.5)
        self.table = tabView()
        self.grid = QGridLayout()
        self.grid.addWidget(self.table,      0,1,1,1)
        self.setLayout(self.grid)

class MyListWidget(QListWidget):
    signal = pyqtSignal()
    def __init__(self, parent=None):
        super(MyListWidget, self).__init__(parent)
        #  self.setIconSize(QtCore.QSize(124, 124))
        # 设置可拖拽
        self.setDragDropMode(QAbstractItemView.DragDrop)
        # 设置多选
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls:
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        endPos = event.pos()
        if event.mimeData().hasUrls:
            event.setDropAction(Qt.CopyAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        endPos = event.pos()
        if event.mimeData().hasUrls:
            event.setDropAction(Qt.CopyAction)
            event.accept()
            links = []
            for url in event.mimeData().urls():
                links.append(str(url.toLocalFile()))
            #  self.emit(SIGNAL("dropped"), links)
        else:
            event.ignore()

    def deleteSelectedItems(self):
        for SelectedItem in self.selectedItems():
            self.takeItem(self.row(SelectedItem))

    def mouseDoubleClickEvent(self, event):
        self.signal.emit()

class TreeWidgetTask_bk(pg.TreeWidget):
    dataSignal = pyqtSignal(dict,list)
    def __init__(self, parent = None):
        super(TreeWidgetTask, self).__init__(parent)
        self.setColumnCount(1)
        self.path_data = os.getcwd()+'/data'
        # self.get_file_list(self.path_data)
        self.setHeaderLabel('设备测试数据列表')
        # 设置多选
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        # 取消拖拽功能
        self.setAcceptDrops(False)
        self.sql = SqlDeal()
        # dev = self.sql.get_device()
        self.get_file_list_db()
        # 右键菜单设置
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.right_menu)

    def right_menu(self):
        self.menu = QMenu()
        deleteAction = QAction("&删除")
        deleteAction.triggered.connect(self.deleteSelected)
        showInfoAction = QAction("&表格数据")
        # showInfoAction.triggered.connect(self.showInfo)
        self.menu.addAction(deleteAction)
        self.menu.addAction(showInfoAction)
        # exportExcleAction = menu.addAction("&导出表格到excel")
        self.menu.exec(QCursor.pos())

    def get_file_list_db(self):
        '''查询数据库，生成文件目录树'''
        dev = self.sql.get_device()
        for d in dev:
            item = QTreeWidgetItem([d.name])
            conditions = d.conditions
            rayType = list(set([ c.rayType for c in conditions]))
            power= list(set([ c.power for c in conditions]))
            _type= list(set([ c.type for c in conditions]))
            for ray in rayType:
                ray_item = QTreeWidgetItem([ray])
                item.addChild(ray_item)
                for _pow in power:
                    pow_item = QTreeWidgetItem([_pow])
                    ray_item.addChild(pow_item)
                    for _t in _type:
                        t_item = QTreeWidgetItem([_t])
                        pow_item.addChild(t_item)
                        for con in conditions:
                            if con.rayType == ray and con.power == _pow and con.type == _t:
                                con_item = QTreeWidgetItem([con.time+'/'+con.ssd+'/'+con.direction+'/'+con.deepth+'/'+con.raySizeX+'*'+con.raySizeY])
                                t_item.addChild(con_item)
            self.addTopLevelItem(item)

    def get_file_list(self, path):
        '''递归遍历文件，生成文件目录树'''
        try:
            files = os.listdir(path)
            for f in files:
                if os.path.isfile(path+'/'+f):
                    item = QTreeWidgetItem([f])
                    self.addTopLevelItem(item)
                if os.path.isdir(path+'/'+f):
                    item = QTreeWidgetItem([f])
                    for c in os.listdir(path+'/'+f):
                        c_item = QTreeWidgetItem([c])
                        item.addChild(c_item)
                    self.addTopLevelItem(item)
        except:
            pass

    def mouseDoubleClickEvent(self, event):
        items = self.selectedItems()
        if len(items) == 1:
            if items[0].childCount()>0:
                # 包含子节点的展开折叠
                if items[0].isExpanded():
                    items[0].setExpanded(False)
                else:
                    items[0].setExpanded(True)
            else:
                # 不包含子节点,直接打开
                item = items[0]
                _time = re.search(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})",item.text(0))
                if _time:
                    conf,data = self.sql.get_condition_data(_time.group(0))
                    self.dataSignal.emit(conf,data)

    def deleteSelected(self):
        '''删除选中'''
        for item in self.selectedItems():
            item_parent = item.parent()
            item_child_count = item.childCount()
            if item_parent and item_child_count == 0: # 没有子节点
                _time = re.search(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})",item.text(0))
                if _time:
                    try:
                        if not QMessageBox.warning(self, '警告', '确认要删除所选数据么,删除后不可恢复？', QMessageBox.Yes|QMessageBox.No)==65536:
                            self.sql.delete_condition_data(_time.group(0))
                            item.parent().removeChild(item)
                    except:
                        QMessageBox.warning(self, '提示', '删除失败！',QMessageBox.Yes)

    def getSelects(self):
        selects = []
        for item in self.selectedItems():
            item_parent = item.parent()
            item_child_count = item.childCount()
            if item_parent and item_child_count == 0:
                path = self.path_data+'/'+item_parent.text(0)+'/'+item.text(0)
                selects.append(path)
            if not item_parent and item_child_count > 0:
                for i in range(0,item_child_count):
                    path = self.path_data+'/'+item.text(0)+'/'+item.child(i).text(0)
                    selects.append(path)
            if not item_parent and item_child_count == 0:
                path = self.path_data+'/'+item.text(0)
                selects.append(path)
        return selects

    def deleteSelectedItems(self):
        selects = self.getSelects()
        for s in selects:
            if os.path.isfile(s):
                os.remove(s)
        # 删除空文件
        for f in os.listdir(self.path_data):
            if os.path.isdir('%s/%s'%(self.path_data,f)):
                if not os.listdir('%s/%s'%(self.path_data,f)):
                    os.removedirs('%s/%s'%(self.path_data,f))
        self.clear()
        self.get_file_list(self.path_data)

class TreeWidgetTask(QTreeWidget):
    dataSignal = pyqtSignal(dict,list)
    def __init__(self, parent = None, sql=None):
        super(TreeWidgetTask, self).__init__(parent)
        self.setColumnCount(1)
        #  self.path_data = os.getcwd()+'/data'
        # self.get_file_list(self.path_data)
        self.setHeaderLabel('设备测试数据列表')
        # 设置多选
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        # 取消拖拽功能
        self.setAcceptDrops(False)
        self.sql = SqlDeal()
        # dev = self.sql.get_device()
        self.get_file_list_db_sql()
        # 右键菜单设置
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.right_menu)

    def right_menu(self):
        self.menu = QMenu()
        updateAction = QAction("&刷新显示",triggered=self.get_file_list_db_sql)
        deleteAction = QAction("&删除")
        exportTmrAction = QAction("&导出TMR")
        deleteAction.triggered.connect(self.deleteSelected)
        exportTmrAction.triggered.connect(self.exportTmr)
        #  showInfoAction = QAction("&表格数据")
        # showInfoAction.triggered.connect(self.showInfo)
        self.menu.addAction(updateAction)
        self.menu.addAction(deleteAction)
        self.menu.addAction(exportTmrAction)
        #  self.menu.addAction(showInfoAction)
        # exportExcleAction = menu.addAction("&导出表格到excel")
        self.menu.exec(QCursor.pos())

    def get_file_list_db(self):
        '''查询数据库，生成文件目录树'''
        dev = self.sql.get_device()
        for d in dev:
            item = QTreeWidgetItem([d.name])
            conditions = d.conditions
            rayType = list(set([ c.rayType for c in conditions]))
            power= list(set([ c.power for c in conditions]))
            _type= list(set([ c.type for c in conditions]))
            for ray in rayType:
                ray_item = QTreeWidgetItem([ray])
                item.addChild(ray_item)
                for _pow in power:
                    pow_item = QTreeWidgetItem([_pow])
                    ray_item.addChild(pow_item)
                    for _t in _type:
                        t_item = QTreeWidgetItem([_t])
                        pow_item.addChild(t_item)
                        for con in conditions:
                            if con.rayType == ray and con.power == _pow and con.type == _t:
                                con_item = QTreeWidgetItem([con.time+'/'+con.ssd+'/'+con.direction+'/'+con.deepth+'/'+con.raySizeX+'*'+con.raySizeY])
                                t_item.addChild(con_item)
            self.addTopLevelItem(item)

    def get_file_list_db_sql(self):
        '''查询数据库，生成文件目录树'''
        self.clear()
        dev = self.sql.get_device_sql()
        for d in dev:
            # item = QTreeWidgetItem([d.name])
            item = QTreeWidgetItem(['%s-%s'%(d['name'],d['room'])])
            conditions = self.sql.get_condition_sql(d['id'])
            rayType = sorted(list(set([ c['rayType'] for c in conditions])))
            power= sorted(list(set([ c['power'] for c in conditions])))
            _type= sorted(list(set([ c['type'] for c in conditions])))
            for ray in rayType:
                ray_item = QTreeWidgetItem([ray])
                item.addChild(ray_item)
                for _pow in power:
                    pow_item = QTreeWidgetItem([_pow])
                    ray_item.addChild(pow_item)
                    for _t in _type:
                        t_item = QTreeWidgetItem([_t])
                        pow_item.addChild(t_item)
                        for con in conditions:
                            if con['rayType'] == ray and con['power'] == _pow and con['type'] == _t:
                                con_item = QTreeWidgetItem([con['time']+'/'+con['ssd']+'/'+con['direction']+'/'+con['deepth']+'/'+con['raySizeX']+'*'+con['raySizeY']])
                                t_item.addChild(con_item)
            self.addTopLevelItem(item)

    def get_file_list(self, path):
        '''递归遍历文件，生成文件目录树'''
        try:
            files = os.listdir(path)
            for f in files:
                if os.path.isfile(path+'/'+f):
                    item = QTreeWidgetItem([f])
                    self.addTopLevelItem(item)
                if os.path.isdir(path+'/'+f):
                    item = QTreeWidgetItem([f])
                    for c in os.listdir(path+'/'+f):
                        c_item = QTreeWidgetItem([c])
                        item.addChild(c_item)
                    self.addTopLevelItem(item)
        except:
            pass

    def mouseDoubleClickEvent(self, event):
        items = self.selectedItems()
        if len(items) == 1:
            if items[0].childCount()>0:
                # 包含子节点的展开折叠
                if items[0].isExpanded():
                    items[0].setExpanded(False)
                else:
                    items[0].setExpanded(True)
            else:
                # 不包含子节点,直接打开
                item = items[0]
                _time = re.search(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})",item.text(0))
                if _time:
                    self.conf,self.data = self.sql.get_condition_data_sql(_time.group(0))
                    self.dataSignal.emit(self.conf,self.data)

    def deleteSelected(self):
        '''删除选中'''
        for item in self.selectedItems():
            item_parent = item.parent()
            item_child_count = item.childCount()
            if item_parent and item_child_count == 0: # 没有子节点
                _time = re.search(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})",item.text(0))
                if _time:
                    try:
                        if not QMessageBox.warning(self, '警告', '确认要删除所选数据么,删除后不可恢复？', QMessageBox.Yes|QMessageBox.No)==65536:
                            self.sql.delete_condition_data(_time.group(0))
                            item.parent().removeChild(item)
                    except:
                        QMessageBox.warning(self, '提示', '删除失败！',QMessageBox.Yes)

    def keyPressEvent(self, event):
        if (event.key() == Qt.Key_Delete):
            self.deleteSelected()
            pass

    def getSelects(self):
        selects = []
        for item in self.selectedItems():
            item_parent = item.parent()
            item_child_count = item.childCount()
            if item_parent and item_child_count == 0:
                path = self.path_data+'/'+item_parent.text(0)+'/'+item.text(0)
                selects.append(path)
            if not item_parent and item_child_count > 0:
                for i in range(0,item_child_count):
                    path = self.path_data+'/'+item.text(0)+'/'+item.child(i).text(0)
                    selects.append(path)
            if not item_parent and item_child_count == 0:
                path = self.path_data+'/'+item.text(0)
                selects.append(path)
        return selects

    def deleteSelectedItems(self):
        selects = self.getSelects()
        for s in selects:
            if os.path.isfile(s):
                os.remove(s)
        # 删除空文件
        for f in os.listdir(self.path_data):
            if os.path.isdir('%s/%s'%(self.path_data,f)):
                if not os.listdir('%s/%s'%(self.path_data,f)):
                    os.removedirs('%s/%s'%(self.path_data,f))
        self.clear()
        self.get_file_list(self.path_data)

    def getMultiPlotData(self):
        '''获取多条曲线数据'''
        info = []
        for item in self.selectedItems():
            _time = re.search(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})",item.text(0))
            if _time:
                conf,data = self.sql.get_condition_data_sql(_time.group(0))
                info.append({
                    'conf':conf,
                    'data':data,
                })
            else:
                QMessageBox.warning(self, '提示', '所选项目[%s]不是有效数据'%item.text[0],QMessageBox.Yes)
        return info

    def exportTmr(self):
        # if self.selectedItems():
        c_list = []
        x_list = []
        y_list = []
        for item in self.selectedItems():
            _time = re.search(r"(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})",item.text(0))
            if _time:
                conf,data = self.sql.get_condition_data_sql(_time.group(0))
                c_list.append(conf)
                tm = data[3]
                ts = data[4]
                repeat  = [float('%.4f'%(m/(s+0.00000001))) for m,s in zip(tm,ts)]
                normal = [float('%.4f'%(100*r/max(repeat))) for r in repeat]
                x_list.append(data[2])
                y_list.append(normal)
            else:
                QMessageBox.warning(self, '提示', '所选项目[%s]不是有效数据'%item.text[0],QMessageBox.Yes)
        self.getTMR(x_list,y_list,c_list)
        # else:
            # QMessageBox.warning(self, '提示', '请选择要导出TMR的数据',QMessageBox.Yes)

    def getTMR(self,x_list,y_list,c):
        '''选中曲线转换tmr文件'''
        try:
            # x_list,y_list,c = self.getPddOarList()
            file_path =  QFileDialog.getSaveFileName(self,"导出TMR文件","" ,"tmr_results files (*.tmr_results);;all files(*.*)")
            filename = file_path[0]
            number = len(x_list)
            with open(filename,'w') as f:
                mat = "{:^10}{:^4} {:^4}\n"
                f.write(mat.format(number,c[0]['power'].replace('MeV',''),'%.1f'%float(c[0]['ssd'].replace('cm',''))))
                n = 0
                for x,y,c in zip(x_list,y_list,c):
                    # con = c.split(',')
                    raysize = c['raySizeX'].replace('cm','')
                    mat = "{:^10}{:^10}  {:^2}\n"
                    f.write(mat.format(n,'%.2f'%float(raysize),60))
                    n += 1
                    x = np.array(x)
                    y = np.array(y)
                    xnew= np.arange(x.min(),x.max(),0.5)
                    func = interpolate.interp1d(x, y, kind='slinear')
                    ynew= func(xnew)
                    # ynew = self.aveFilter(ynew,4)
                    for i in range(0,len(xnew)):
                        if xnew[i] > 0 and xnew[i]%5 == 0:
                            mat = "{:^13}  {:^7}\n"
                            f.write(mat.format('%.5f'%(xnew[i]/10.0),'%.5f'%(ynew[i]/100.0)))
                    f.write(mat.format('%.5f'%(30.0),'%.5f'%(ynew[-1]/100.0)))
            QMessageBox.information( self, '提示','导出TMR完成', QMessageBox.Yes)
        except:
            QMessageBox.information( self, '提示','导出TMR失败', QMessageBox.Yes)

class TaskWidget(QDockWidget):
    def __init__(self, parent = None):
        super(ConfigDockWidget, self).__init__(parent)
        self.setWindowTitle('操作')
        self.btn_openTask = QPushButton('添加数据文件')
        self.btn_openTask.clicked.connect(self.openTask)
        self.showData = QPushButton('显示数据')
        self.showData.clicked.connect(self.btn_showData)
        self.showLine = QPushButton('显示曲线')
        self.showLine.clicked.connect(self.btn_showLine)

        self.btn_getTmr= QPushButton('导出tmr')
        self.btn_getTmr.clicked.connect(self.getTMR)
        self.btn_showTmr= QPushButton('tmr')
        self.btn_showTmr.clicked.connect(self.showTMR)

        self.TaskList = MyListWidget()

        self.layout_btn = QGridLayout()
        self.layout_btn.addWidget(self.btn_openTask, 0,0,1,1)
        self.layout_btn.addWidget(self.showData,     1,0,1,1)
        self.layout_btn.addWidget(self.showLine,     1,1,1,1)
        self.layout_btn.addWidget(self.btn_getTmr,   2,0,1,1)
        self.layout_btn.addWidget(self.btn_showTmr,  2,1,1,1)
        self.layout_btn.addWidget(self.TaskList,     3,0,1,2)
        self.dockWidgetContents = QWidget()
        self.setWidget(self.dockWidgetContents)

from MultiLineAnalyseDialog import MultiLineDialog
from ui.chartAnalyse import Ui_Form as ChartAnalyseForm
class chartAnalyseForm(QWidget, ChartAnalyseForm):
    def __init__(self, parent = None):
        super(chartAnalyseForm, self).__init__(parent)
        self.setupUi(self)
        self.setWindowIcon(QIcon(':icons/images_rc/chartAnalyse.png'))
        if SKIN == 'style_Dark':
            self.setStyleSheet(PyQt5_stylesheets.load_stylesheet_pyqt5(style=SKIN))
        if SKIN == 'style_Default':
            pass
        # w = GetSystemMetrics (0)
        # h = GetSystemMetrics (1)
        # self.setMinimumSize(w/1.2,h/1.2)
        # 图形
        self.chart_pdd = GraphWindow()
        self.chart_x = GraphWindow()
        self.chart_y = GraphWindow()
        self.chart_3D = AnalyseGlWidget()
        self.scan_chart = AnalyseGlWidget()
        self.multiLineDlg = MultiLineDialog()
        # 任务目录树显示
        self.TaskTree = TreeWidgetTask()
        self.TaskTree.dataSignal.connect(self.showOneLine)
        # self.TaskTree.setFixedSize(w/1.2*2/5, h/1.2)
        self.tableTask = tabViewTask()
        self.tableTask.clicked.connect(self.btn_search_data)
        # 表格
        self.tableData = tabView()

        self.verticalLayout.addWidget(self.TaskTree)
        self.verticalLayout_pdd.addWidget(self.chart_pdd)
        self.verticalLayout_x.addWidget(self.chart_x)
        self.verticalLayout_y.addWidget(self.chart_y)
        self.verticalLayout_3d.addWidget(self.chart_3D)
        self.verticalLayout_table.addWidget(self.tableData)

        # self.btn_openTask = QPushButton('添加数据')
        # self.btn_openTask.clicked.connect(self.openTask)
        # self.btn_removeTask = QPushButton('移除数据')
        # self.showData = QPushButton('显示数据')
        # self.showData.clicked.connect(self.btn_showData)
        # self.showLine = QPushButton('显示曲线')
        # self.showLine.clicked.connect(self.btn_showLine)
        # self.exportExcel = QPushButton('导出excel')
        # self.exportExcel.clicked.connect(self.exportDataToExcel)

        self.pushButton_exportTmr.clicked.connect(self.TaskTree.exportTmr)
        self.pushButton_analyseTmr.clicked.connect(self.showTMR)
        # self.btn_getTmr= QPushButton('导出tmr')
        # self.btn_getTmr.clicked.connect(self.getTMR)
        # self.btn_showTmr= QPushButton('tmr')
        # self.btn_showTmr.clicked.connect(self.showTMR)

        self.pushButton_exportExcel.clicked.connect(self.handleExportExcel)
        self.pushButton_multiLine.clicked.connect(self.showMultiLine)
        # 打印机配置信息
        self.current_print = []

    def openTask(self):
        f = QFileDialog(self)
        f.setWindowTitle(r'打开文件')
        import os
        f.setDirectory(os.getcwd()+'/data')
        f.setNameFilter(r'All Files(*);;PDD Files(*.pdd);;OAR Files(*.oar);;SCAN Files(*.scan)')
        f.setFileMode(QFileDialog.ExistingFiles)
        if f.exec() == QDialog.Accepted:
            files = f.selectedFiles()
            self.TaskList.addItems(files)
            for nf in files:
                self.getPddOar(nf)

    def pddImport(self,pddoar):
        filedlg = QFileDialog()
        if pddoar == 'pdd':
            filedlg.setWindowTitle('选择pdd文件')
            filedlg.setNameFilters(['pdd file (*.pdd)','pdd file (*.PDD)'])
        if pddoar == 'oar':
            filedlg.setWindowTitle('选择oar文件')
            filedlg.setNameFilters(['oar file (*.oar)'])
        filedlg.setFileMode(QFileDialog.ExistingFiles)
        filelist = None
        filename = []
        linelist = []
        if(filedlg.exec() == QDialog.Accepted):
            filelist = filedlg.selectedFiles()
            d = self.readfile(filelist[0],pddoar,'gb2312')
            if len(filelist) > 1:
                try:
                    for file in filelist:
                        try:
                            d = self.readfile(file,pddoar,'gb2312')
                        except:
                            d = self.readfile(file,pddoar,'utf8')
                        finally:
                            pass
                        if d['X']:
                            if pddoar == 'pdd':
                                linelist.append([d['Z'],d['normalization']])
                                filename.append(os.path.split(file)[1])
                            if pddoar == 'oar':
                                linelist.append([d['Y'],d['normalization']])
                                filename.append(os.path.split(file)[1])
                    if pddoar == 'pdd':
                        self.chart.pddPlots(linelist,filename)
                    if pddoar == 'oar':
                        self.chart.oarPlots(linelist,filename)
                except Exception as e:
                    QMessageBox.information( self, '提示','打开文件中有不支持曲线显示', QMessageBox.Yes)
            else:
                try:
                    try:
                        d = self.readfile(filelist[0],pddoar,'gb2312')
                    except:
                        d = self.readfile(filelist[0],pddoar,'utf8')
                    if d:
                        data = [d['time'],d['X'],d['Y'],d['Z'],d['Tm'],d['Ts'],d['Repeatability'],d['normalization']]
                        self.table.add_excel_data(data)
                        if pddoar == 'pdd':
                            self.addPddfileToSql(d)
                            self.chart.pddPlot(d,self.label_axis)
                        if pddoar == 'oar':
                            self.addOarfileToSql(d)
                            self.chart.oarPlot(d,self.label_axis)
                except Exception as e:
                    QMessageBox.information( self, '提示','打开文件不支持曲线显示', QMessageBox.Yes)

    def addOarfileToSql(self,d):
        from datetime import datetime
        oar = Oar(
                machType  = str(d['testType']),
                machPower = str(d['Power']),
                ray       = str(d['rayType']),
                ray_step  = str('rayStep'),
                size      = str(d['raySize']),
                start     = str(d['X'][0]),
                end       = str(d['X'][-1]),
                edge      = str('edgeFiled'),
                edge_step = str('edgeStep'),
                deepth    = str('deepth'),
                ssd       = str('SSD'),
                direction = str('direction'),
                time      = datetime.now())
        for c1,c2,c3,c4,c5,c6,c7 in zip(d['X'],d['Y'],d['Z'],d['Tm'],d['Ts'],d['Repeatability'],d['normalization']):
            data = OarData(x=float(c1),y=float(c2),z=float(c3),tm=float(c4),ts=float(c5),repeat=float(c6),normal=float(c7))
            oar.oardata.append(data)
        session.add(oar)
        session.commit()

    def addPddfileToSql(self,d):
        from datetime import datetime
        pdd = Pdd(machType  = d['testType'],
                machPower = d['Power'],
                ray       = d['rayType'],
                size      = d['raySize'],
                start     = str('directionAxis'),
                end       = str('directionAxis'),
                step      = str('step'),
                deepth    = str('distance'),
                ssd       = str(d['SSD']),
                time      = datetime.now())
        for c1,c2,c3,c4,c5,c6,c7 in zip(d['X'],d['Y'],d['Z'],d['Tm'],d['Ts'],d['Repeatability'],d['normalization']):
            data = PddData(x=float(c1),y=float(c2),z=float(c3),tm=float(c4),ts=float(c5),repeat=float(c6),normal=float(c7))
            pdd.pdddata.append(data)
        session.add(pdd)
        session.commit()

    def Import(self,pddoar):
        filedlg = QFileDialog()
        if pddoar == 'pdd':
            filedlg.setWindowTitle('选择pdd文件')
            filedlg.setNameFilters(['pdd file (*.pdd)','pdd file (*.PDD)'])
        if pddoar == 'oar':
            filedlg.setWindowTitle('选择oar文件')
            filedlg.setNameFilters(['oar file (*.oar)'])
        filedlg.setFileMode(QFileDialog.ExistingFiles)
        filelist = None
        filename = []
        linelist = []
        if(filedlg.exec() == QDialog.Accepted):
            filelist = filedlg.selectedFiles()
            if len(filelist) > 1:
                try:
                    for file in filelist:
                        try:
                            d = self.readfile(file,pddoar,'gb2312')
                        except:
                            d = self.readfile(file,pddoar,'utf8')
                        finally:
                            pass
                        if d['X']:
                            if pddoar == 'pdd':
                                linelist.append([d['Z'],d['normalization']])
                                filename.append(os.path.split(file)[1])
                            if pddoar == 'oar':
                                linelist.append([d['Y'],d['normalization']])
                                filename.append(os.path.split(file)[1])
                    if pddoar == 'pdd':
                        self.chart.pddPlots(linelist,filename)
                    if pddoar == 'oar':
                        self.chart.oarPlots(linelist,filename)
                except Exception as e:
                    QMessageBox.information( self, '提示','打开文件中有不支持曲线显示', QMessageBox.Yes)
            else:
                try:
                    try:
                        d = self.readfile(filelist[0],pddoar,'gb2312')
                    except:
                        d = self.readfile(filelist[0],pddoar,'utf8')
                    if d:
                        data = [d['time'],d['X'],d['Y'],d['Z'],d['Tm'],d['Ts'],d['Repeatability'],d['normalization']]
                        self.table.add_excel_data(data)
                        if pddoar == 'pdd':
                            self.chart.pddPlot(d,self.label_axis)
                        if pddoar == 'oar':
                            self.chart.oarPlot(d,self.label_axis)
                except Exception as e:
                    QMessageBox.information( self, '提示','打开文件不支持曲线显示', QMessageBox.Yes)

    def readfile(self, file_path, pddoar,filetype):
        time = []
        x = []
        y = []
        z = []
        Tm = []
        Ts = []
        Repeat= []
        normal= []
        pdd = None
        oar = None
        testType = None
        rayType = None
        raySize = None
        Power= None
        SSD = None
        testDeepth= None
        data = None
        if filetype == 'gb2312':
            # 打开gb2312类型文件
            #  with codecs.open(file_path, 'r', 'gb2312', errors='ignore') as f:
                #  data = f.readlines()
            with open('%s'%file_path,'r') as f:
                data = f.readlines()
        if filetype == 'utf8':
            with open('%s'%file_path,'r') as f:
                data = f.readlines()
        for line in data:
            n = line.replace('\r\n','')
            n = line.replace('\n','')
            n = n.split(',')
            try:
                if len(n)==8:
                    time.append(str(n[0]))
                    x.append(float(n[1]))
                    y.append(float(n[2]))
                    z.append(float(n[3]))
                    Tm.append(float(n[4]))
                    Ts.append(float(n[5]))
                    Repeat.append(float(n[6]))
                    normal.append(float(n[7]))
                if line.find('TestType')>=0:
                    testType = line.split(':')[1]
                if line.find('RayType')>=0:
                    rayType = line.split(':')[1]
                if line.find('RaySize')>=0:
                    raySize = line.split(':')[1]
                if line.find('Power'):
                    Power = line.split(':')[1]
                if line.find('SSD')>=0:
                    SSD = line.split('=')[1]
                if line.find('TestDeepth')>=0:
                    testDeepth = line.split('=')[1]
            except Exception as e:
                print(e)
                pass
        l = len(Tm)
        #　计算重复性
        # Repeat  = [float('%.4f'%(Tm[i]/(Ts[i]+0.00001))) for i in range(0,l)]
        #　计算归一化
        if pddoar == 'pdd':
            # dR_max = max(Repeat)
            # normal = [float('%.4f'%(Repeat[i]/dR_max)) for i in range(0,l)]
            pdd = [float('%.4f'%(100*normal[i])) for i in range(0,l)]
        if pddoar == 'oar':
            # dR_zero = Repeat[y.index(0)]
            # normal = [float('%.4f'%(Repeat[i]/dR_zero)) for i in range(0,l)]
            oar = [float('%.4f'%(100*normal[i])) for i in range(0,l)]
        ret = { 'time':time,
                'Y':y,
                'X':x,
                'Tm':Tm,
                'Ts':Ts,
                'Z':z,
                'pdd':pdd,
                'oar':oar,
                'Power':Power,
                'Repeatability':Repeat,
                'normalization':normal,
                'testType':testType,
                'testDeepth':testDeepth,
                'rayType':rayType,
                'raySize':raySize,
                'SSD':SSD }
        return ret

    def btn_search(self):
        '''查询任务列表'''
        date = self.dateEdit.dateTime().toString(Qt.ISODate)[0:7]
        data = []
        self.TaskList.clear()
        if self.radio_pdd.isChecked():
            res = session.query(Condition).filter(Condition.type=='pdd').filter(Condition.time.like('%%%s%%'%(date))).all()
        else:
            res = session.query(Condition).filter(Condition.type=='oar').filter(Condition.time.like('%%%s%%'%(date))).all()
        for r in res:
            d = r.name.split(',')
            inf = '光机:%s 能量:%s 源波距:%s 射野:%s'%(d[0],d[1],d[2],d[3])
            data.append(''+str(r.time)+'\r\n'+'   '+inf)
        if data:
            self.TaskList.addItems(data)

    def btn_search_data(self):
        '''查询数据'''
        span=3
        try:
            time = self.tableTask.click_data[0]
            #  _type = self.tableTask.click_data[2]
        except:
            QMessageBox.information( self, '提示','请选中要查询的任务', QMessageBox.Yes)
            return
        #  if _type.find('pdd')>=0:
        if self.radio_pdd.isChecked():
            res = session.query(Data).filter(Condition.time==time).filter(Condition.id==Data.condition_id).all()
            data = []
            y = []
            x = []
            for r in res:
                data.append([r.x,r.y,r.z,r.tm,r.ts,r.repeat,r.normal])
                x.append(r.z)
                y.append(float('%.4f'%(100*r.normal)))
            self.table.addData(data)

            p = session.query(Condition).filter(Condition.time==time).first()
            try:
                self.chart.tunnelLine.setTitle('拟合曲线')
                self.chart.pddPlot(x,y,p.size,p.machType,p.ray,span)
                self.chart_history.tunnelLine.setTitle('原始曲线')
                self.chart_history.pddPlotHistory(x,y,p.size,p.machType,p.ray)
            except:
                QMessageBox.warning(self,'错误','曲线参数错误',QMessageBox.Yes)

        if self.radio_oar.isChecked():
        #  if _type.find('oar')>=0:
            res = session.query(Data).filter(Condition.time==time).filter(Condition.id==Data.condition_id).all()
            #  res = session.query(OarData).filter(Oar.time==time).filter(Oar.id==OarData.oar_id).all()
            x = []
            y = []
            data = []
            direction = self.tableTask.click_data[10]
            for r in res:
                data.append([r.x,r.y,r.z,r.tm,r.ts,r.repeat,r.normal])
                if direction == 'x':
                    x.append(r.x)
                elif direction == 'y':
                    x.append(r.y)
                elif direction == 'y=x':
                    x.append(r.x)
                elif direction == 'y=-x':
                    x.append(r.x)
                else:
                    x.append(r.y)
                y.append(float('%.4f'%(100*r.normal)))
            self.dlg = DataDialog()
            self.dlg.table.addData(data)
            self.dlg.show()
            #  self.table.addData(data)
            #  o = session.query(Oar).filter(Oar.time==time).first()
            p = session.query(Condition).filter(Condition.time==time).first()
            try:
                self.chart.tunnelLine.setTitle('拟合曲线')
                self.chart.oarPlot(x,y,o.size,o.machType,o.ray,span)
                self.chart_history.tunnelLine.setTitle('原始曲线')
                self.chart_history.oarPlotHistory(x,y,o.size,o.machType,o.ray)
            except:
                QMessageBox.warning(self,'错误','曲线参数错误',QMessageBox.Yes)

    def getOneLineData(self, path):
        data,config = self.getPddOar(path)
        if data and config:
            direction = config['direction']
            raysize = config['raysize']
            _type = config['type']
            if _type == 'oar':
                if direction == "G->T" or direction == "T->G":
                    x = [i[1] for i in data]
                else:
                    x = [i[0] for i in data]
                self.chart.setVisible(True)
                self.scan_chart.setVisible(False)
            if _type == 'pdd':
                x = [i[2] for i in data]
                self.chart.setVisible(True)
                self.scan_chart.setVisible(False)
            if _type == 'ebeam':
                x = [i[2] for i in data]
                y = [i[3] for i in data]
                y = [100*y_/max(y) for y_ in y]
                self.chart.setVisible(True)
                self.scan_chart.setVisible(False)
                return x,y,'',config
            if _type == 'scan':
                def get_canvas_xyz(data,raysize,step):
                    inv = int(int(raysize)*10/int(step))+1
                    d = [data[i*inv:i*inv+inv] for i in range(0,int(len(data)/inv))]
                    x_new = []
                    y_new = []
                    z_new = []
                    for c in d:
                        x = [u[0] for u in c]
                        y = [u[1] for u in c]
                        z = [u[-1] for u in c]
                        x_new.append(x)
                        y_new.append(y)
                        z_new.append(z)
                    return x_new,y_new,z_new
                step = abs(data[0][0] - data[1][0])
                if step == 0:
                    step = abs(data[0][1] - data[1][1])
                x,y,z = get_canvas_xyz(data,raysize,step)
                return x,y,z,config
            y = [float('%.4f'%(100*d[-1])) for d in data]
            return x,y,'',config
        else:
            return False,False,False,False

    def showOneLine(self,conf,data):
        print(conf)
        print(data)
        # try:
        x = data[0]
        y = data[1]
        z = data[2]
        tm = data[3]
        ts = data[4]
        s = '射束类型:%s 能量:%s 源皮距:%s 深度:%s 方向:%s 射野X:%s*%s'%(conf['rayType'],conf['power'],conf['ssd'],conf['deepth'],conf['direction'],conf['raySizeX'],conf['raySizeY'])
        if conf['type'] == 'PDD':
            repeat  = [float('%.4f'%(m/(s+0.00000001))) for m,s in zip(tm,ts)]
            normal = [float('%.4f'%(100*r/max(repeat))) for r in repeat]
            if conf['rayType'] == '电子':
                self.chart_pdd.getEbeamPdd(z,normal,conf['raySizeX'])
            if conf['rayType'] == '光子':
                self.chart_pdd.getPhotonPdd(z,normal,conf['raySizeX'])
            self.tableData.addData([x,y,z,tm,ts,repeat,normal])
            self.chart_pdd.tunnelLine.setTitle(s)
            self.tabWidget.setCurrentIndex(0)
            self.current_print={'config':conf,'result':self.chart_pdd.pdd_result}
            # 赋值给TMR数据
            self.TMR_conf = conf
            self.TMR_x = z
            self.TMR_normal = normal
        if conf['type'] == 'OAR':
            repeat  = [float('%.4f'%(m/(s+0.00000001))) for m,s in zip(tm,ts)]
            normal = [float('%.4f'%(100*r/max(repeat))) for r in repeat]
            # try:
            self.tableData.addData([x,y,z,tm,ts,repeat,normal])
            if conf['direction'] == 'A->B' or conf['direction'] == 'B->A':
                if conf['rayType'] == '电子':
                    self.chart_x.getEbeamOar(x,normal,conf['raySizeX'])
                if conf['rayType'] == '光子':
                    self.chart_x.getPhotonOar(x,normal,conf['raySizeX'])
                self.chart_x.tunnelLine.setTitle(s)
                self.tabWidget.setCurrentIndex(1)
                self.current_print={'config':conf,'result':self.chart_x.oar_result}
            elif conf['direction'] == 'G->T' or conf['direction'] == 'T->G':
                if conf['rayType'] == '电子':
                    self.chart_y.getEbeamOar(y,normal,conf['raySizeX'])
                if conf['rayType'] == '光子':
                    self.chart_y.getPhotonOar(y,normal,conf['raySizeX'])
                self.chart_y.tunnelLine.setTitle(s)
                self.tabWidget.setCurrentIndex(2)
                self.current_print={'config':conf,'result':self.chart_y.oar_result}
            else:
                self.tabWidget.setCurrentIndex(1)
                self.chart_x.tunnelLine.setTitle(s)
                self.chart_x.oarPlot(x,normal,conf['raySizeX'])
                self.chart_y.tunnelLine.setTitle(s)
                self.chart_y.oarPlot(y,normal,conf['raySizeY'])
                self.current_print={'config':conf,'result':self.chart_x.oar_result}
            self.chart_3D.title = s
            self.chart_3D.drawLine(x,y,normal,conf['raySizeY'])
        if conf['type'] == 'SCAN':
            self.chart_3D.title = s
            normal = [float('%.4f'%(100*r/max(tm))) for r in tm]
            self.tableData.addData([x,y,z,tm,ts,normal,ts])
            self.chart_3D.updateSurface(x,y,normal,conf['raySizeX'])
            self.tabWidget.setCurrentIndex(3)
        # except:
            # QMessageBox.warning(self, '提示', '数据错误,无法显示曲线', QMessageBox.Yes)

    def showMultiLine(self):
        lines = self.TaskTree.getMultiPlotData()
        print(lines)
        x_list = []
        y_list = []
        c_list = []
        for l in lines:
            data = l['data']
            conf = l['conf']
            x = data[0]
            y = data[1]
            z = data[2]
            tm = data[3]
            ts = data[4]
            repeat  = [float('%.4f'%(m/(s+0.00000001))) for m,s in zip(tm,ts)]
            normal = [float('%.4f'%(100*r/max(repeat))) for r in repeat]
            if conf['type'] == 'PDD':
                axis_x = z
            if conf['type'] == 'OAR':
                if conf['direction'] == 'G->T' or conf['direction'] == 'T->G':
                    axis_x = y
                else:
                    axis_x = x
            axis_y = normal
            x_list.append(axis_x)
            y_list.append(axis_y)
            c_list.append(conf)
        self.multiLineDlg.chart.multiLine(x_list,y_list,c_list)
        self.multiLineDlg.show()
        # self.chart_pdd.multiLine(x_list,y_list,c_list)

    def btn_showLine(self):
        '''按钮显示曲线功能'''
        selects = self.TaskTree.getSelects()
        if selects:
            pdd = [s for s in selects if s.endswith('.pdd')]
            oar = [s for s in selects if s.endswith('.oar')]
            scan = [s for s in selects if s.endswith('.scan')]
            def getList(selects):
                x_list = []
                y_list = []
                config_list = []
                for s in selects:
                    x,y,z,c = self.getOneLineData(s)
                    if x and y and c:
                        x_list.append(x)
                        y_list.append(y)
                        config_list.append(c)
                    else:
                        QMessageBox.information( self, '提示','%s 文件数据错误'%s, QMessageBox.Yes)
                return x_list,y_list,config_list
            # 显示pdd
            x_list, y_list, config_list = getList(pdd)
            if x_list:
                if len(x_list) == 1:
                    self.showOneLine(pdd[0])
                else:
                    self.multiChart_pdd = GraphWindow()
                    self.multiChart_pdd.setWindowTitle('PDD多曲线对比显示')
                    c = [c['type']+':'+c['direction'] for c in config_list]
                    self.multiChart_pdd.multiLine(x_list,y_list,c)
                    self.multiChart_pdd.show()
            # 显示oar
            x_list, y_list, config_list = getList(oar)
            if x_list:
                if len(x_list) == 1:
                    self.showOneLine(oar[0])
                else:
                    self.multiChart_oar = GraphWindow()
                    self.multiChart_oar.setWindowTitle('OAR多曲线对比显示')
                    c = [c['type']+':'+c['direction'] for c in config_list]
                    self.multiChart_oar.multiLine(x_list,y_list,c)
                    self.multiChart_oar.show()
            # 显示scan
            # x_list, y_list, config_list = getList(scan)
            # if x_list:
                # self.multiChart_scan = GraphWindow()
                # c = [c['type']+c['direction'] for c in config_list]
                # self.multiChart_scan.multiLine(x_list,y_list,c)
                # self.multiChart_scan.show()

            return
        else:
            QMessageBox.information( self, '提示','未选中文件', QMessageBox.Yes)

    def btn_showData(self):
        '''显示选中任务的数据'''
        selects = self.TaskTree.getSelects()
        if selects:
            self.dlg = []
            for s in selects:
                data,config = self.getPddOar(s)
                if data and config:
                    dlg = DataDialog()
                    dlg.setWindowTitle(s)
                    dlg.table.addData(data)
                    self.dlg.append(dlg)
                else:
                    QMessageBox.information( self, '提示','%s 文件数据错误'%s, QMessageBox.Yes)
            for d in self.dlg:
                d.show()
        else:
            QMessageBox.information( self, '提示','未选中文件', QMessageBox.Yes)

    def getPddOar(self,filename):
        '''计算pdd或oar重复性和归一化，
        并导出表格数据为.pdd文件或.oar文件'''
        try:
            with open('%s'%filename,'r') as f:
                lines = f.readlines()
            for i in range(0,len(lines)):
                if lines[i].find('[DATA]')>=0:
                    data_index = i
                if lines[i].find('[CONFIG]')>=0:
                    config_index = i
            data = lines[data_index+2:config_index-1]
            x = []
            y = []
            z = []
            Tm = []
            Ts = []
            row= len(data)
            for d in data:
                d_s = d.replace('\n','').split(',')
                x.append(float(d_s[1]))
                y.append(float(d_s[2]))
                z.append(float(d_s[3]))
                Tm.append(float(d_s[4]))
                Ts.append(float(d_s[5]))
            #　计算重复性
            try:
                Repeat  = [float('%.4f'%(Tm[i]/(Ts[i]))) for i in range(0,row)]
            except:
                Repeat  = [float('%.4f'%(Tm[i]/(Ts[i]+0.00000001))) for i in range(0,row)]
            #　计算归一化
            dR_max = max(Repeat)
            normal = [float('%.4f'%(Repeat[i]/dR_max)) for i in range(0,row)]
            data = [list(temp) for temp in zip(x,y,z,Tm,Ts,Repeat,normal)]
            # 获取配置信息
            config = lines[config_index+1:]
            conf = {
                'type'               :config[0].replace('\n','').replace(' ','').split(':')[1],
                'electrometer'       :config[1].replace('\n','').replace(' ','').split(':')[1],
                'power'              :config[2].replace('\n','').replace(' ','').split(':')[1],
                'raysize'            :config[3].replace('\n','').replace(' ','').split(':')[1],
                'ssd'                :config[4].replace('\n','').replace(' ','').split(':')[1],
                'deepth'             :config[5].replace('\n','').replace(' ','').split(':')[1],
                'direction'          :config[6].replace('\n','').replace(' ','').split(':')[1],
            }
            return data,conf
        except:
            return False,False
            # QMessageBox.warning( self, '警告','打开文件错误,格式不支持', QMessageBox.Yes)

    def getPddOarList(self):
        selects = self.TaskTree.getSelects()
        if selects:
            pdd = [s for s in selects if s.endswith('.pdd')]
            if pdd:
                x_list = []
                y_list = []
                config_list = []
                # for item in self.TaskList.selectedItems():
                for item in pdd:
                    # t = item.text()
                    data,config = self.getPddOar(item)
                    direction = config['direction']
                    raysize = config['raysize']
                    _type = config['type']
                    if _type == 'oar':
                        if direction == "G->T" or direction == "T->G":
                            x = [i[1] for i in data]
                        else:
                            x = [i[0] for i in data]
                    if _type == 'pdd':
                        x = [i[2] for i in data]
                    y = [float('%.4f'%(100*d[-1])) for d in data]
                    x_list.append(x)
                    y_list.append(y)
                    config_list.append(config)
                return x_list,y_list,config_list

    def exportDataToExcel(self):
        '''显示选中任务的曲线'''
        if len(self.TaskList.selectedItems())<1:
            QMessageBox.information( self, '提示','未选中文件', QMessageBox.Yes)
            return
        try:
            for item in self.TaskList.selectedItems():
                t = item.text()
                data,config = self.getPddOar(t)
                direction = config['direction']
                raysize = config['raysize']
                _type = config['type']
                s = '光机:%s 能量:%seMv 源波距:%scm 射野:%scm 方向:%s'%(config['electrometer'],config['power'],config['ssd'],config['raysize'],config['direction'])
                self.chart.tunnelLine.setTitle(s)
                y = [float('%.4f'%(100*d[-1])) for d in data]
                if _type == 'oar':
                    if direction == "G->T" or direction == "T->G":
                        x = [i[1] for i in data]
                    else:
                        x = [i[0] for i in data]
                    self.chart.oarPlot(x,y,raysize)
                if _type == 'pdd':
                    x = [i[2] for i in data]
                    self.chart.pddPlot(x,y,raysize)

                import xlsxwriter
                book = xlsxwriter.Workbook('test.xlsx')
                sheet = book.add_worksheet('sheet1')
                for i in range(0,len(data)):
                    for j in range(0,len(data[i])):
                        sheet.write(i, j, data[i][j])
                self.chart.grab().save('chart.png')
                sheet.insert_image('D10','chart.png')
                book.close()
        except:
            QMessageBox.warning( self, '警告','导出excel数据错误', QMessageBox.Yes)

    def getTMR(self):
        '''选中曲线转换tmr文件'''
        x_list = self.TMR_x
        y_list = self.TMR_normal
        c = self.TMR_conf
        if 1:
        # try:
            # x_list,y_list,c = self.getPddOarList()
            file_path =  QFileDialog.getSaveFileName(self,"导出TMR文件","" ,"tmr_results files (*.tmr_results);;all files(*.*)")
            filename = file_path[0]
            number = len(x_list)
            with open(filename,'w') as f:
                mat = "{:^10}{:^4} {:^4}\n"
                f.write(mat.format(number,c[0]['power'].replace('MeV',''),'%.1f'%float(c[0]['ssd'].replace('cm',''))))
                n = 0
                for x,y,c in zip(x_list,y_list,c):
                    # con = c.split(',')
                    raysize = c['raySizeX'].replace('cm','')
                    mat = "{:^10}{:^10}  {:^2}\n"
                    f.write(mat.format(n,'%.2f'%float(raysize),60))
                    n += 1
                    x = np.array(x)
                    y = np.array(y)
                    xnew= np.arange(x.min(),x.max(),0.5)
                    func = interpolate.interp1d(x, y, kind='slinear')
                    ynew= func(xnew)
                    # ynew = self.aveFilter(ynew,4)
                    for i in range(0,len(xnew)):
                        if xnew[i] > 0 and xnew[i]%5 == 0:
                            mat = "{:^13}  {:^7}\n"
                            f.write(mat.format('%.5f'%(xnew[i]/10.0),'%.5f'%(ynew[i]/100.0)))
                    f.write(mat.format('%.5f'%(30.0),'%.5f'%(ynew[-1]/100.0)))
            QMessageBox.information( self, '提示','导出TMR完成', QMessageBox.Yes)
        # except:
            # QMessageBox.information( self, '提示','导出数据出错', QMessageBox.Yes)

    def showTMR(self):
        win32api.ShellExecute(0, 'open', '%s/TMR/pddtotmr.exe'%os.getcwd(), '','',1)

    def aveFilter(self,y,span):
        '''均值滤波
        span = 5:
        y(1) = y(1)
        y(2) = y(1)+y(2)+y(3)/3
        y(3) = y(1)+y(2)+y(3)+y(4)+y(5)/5
        '''
        # span = 7
        s = 0
        cen = int(span/2)
        for i in range(0,len(y)):
            if i >= cen:
                y_t = y[i-cen:i+cen]
                if len(y)-i<=cen:
                    y[i]= y[i]
                else:
                    y[i]= sum(y_t)/len(y_t)
            elif 0<i<cen :
                s = s+2
                y_t = y[0:s+1]
                y[i]= sum(y_t)/len(y_t)
        return y

    def handlePaintRequest(self, printer):
        """打印函数"""
        document = QTextDocument()
        cursor = QTextCursor(document)
        cursor.movePosition(QTextCursor.Start)
        # 框架
        topFrame = cursor.currentFrame()
        topFrameFormat = topFrame.frameFormat()
        topFrameFormat.setPadding(16)
        topFrame.setFrameFormat(topFrameFormat)
        # 文本框架
        textFormat = QTextCharFormat()
        # 文本字体加粗框架
        boldFormat = QTextCharFormat()
        boldFormat.setFontWeight(QFont.Bold)
        conf = self.current_print['config']
        _time     = ": "+ time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        time_pre  = ": " + str(conf["time"])
        rayType   = ": " + str(conf["rayType"])
        power     = ": " + str(conf["power"])
        ssd       = ": " + str(conf["ssd"])
        direction = ": " + str(conf["direction"])
        deepth    = ": " + str(conf["deepth"])
        name      = ": " + str(conf["name"])
        room      = ": " + str(conf["room"])
        result    = self.current_print['result']
        if conf['type'] == "PDD":
            cursor.insertText("\t\t\t\t%-8s"%("PDD测量数据结果"),boldFormat)
            cursor.insertBlock()
            cursor.insertBlock()
            D0        = ": " + "%.2f %%"%(result["D0"])
            D10       = ": " + "%.2f %%"%(result["D10"])
            D20       = ": " + "%.2f %%"%(result["D20"])
            D20_D10   = ": " + "%.2f   "%(result["D20_D10"])
            R_max     = ": " + "%.2f   "%(result["R100"])
            R_80      = ": " + "%.2f mm"%(result["R80"])
            R_50      = ": " + "%.2f mm"%(result["R50"])
            Enery     = ": " + "%.2f MeV"%(result["energy"])
            orderItems = [[x,y] for x,y in zip(result["x"],result["y"])]
            cursor.insertText("%-8s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("射束类型",rayType,"D0",D0,"打印时间",_time),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("能量",power,"D10",D10,"测量日期",time_pre),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-9s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("源皮距",ssd,"D20",D20,"设备名称",name),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("方向",direction,"D20/D10",D20_D10,"房间名称",room),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("深度",deepth,"R_max",R_max,"",""),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("","","R_80",R_80,'',''),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("","","R_50",R_50,'',''),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("","","Enery",Enery,'',''),textFormat)
        if conf['type'] == "OAR":
            cursor.insertText("\t\t\t\t%-8s"%("OAR测量数据结果"),boldFormat)
            cursor.insertBlock()
            cursor.insertBlock()
            Dev          = ": " + "%.2f %%"%(result["Dev"])
            flatValue    = ": " + "%.2f %%"%(result["flatValue"])
            sym          = ": " + "%.2f %%"%(result["sym"])
            Dmin         = ": " + "%.2f %%"%(result["Dmin"])
            left_shadow  = ": " + "%.2f"%(result["left_shadow"])
            right_shadow = ": " + "%.2f"%(result["right_shadow"])
            orderItems   = [[x,y] for x,y in zip(result["x"],result["y"])]
            cursor.insertText("%-8s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("射束类型",rayType,"光野重合性",Dev,"打印时间",_time),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("能量",power,"均整度",flatValue,"测量日期",time_pre),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-9s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("源皮距",ssd,"对称性",sym,"设备名称",name),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("方向",direction,"最小剂量率",Dmin,"设备房间",room),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("深度",deepth,"左半影",left_shadow,'',''),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("","","右半影",right_shadow,'',''),textFormat)
        if conf['type'] == "EBEAM":
            cursor.insertText("\t\t\t\t%-8s"%("EBEAM测量数据结果"),boldFormat)
            cursor.insertBlock()
            cursor.insertBlock()
            R100      = ": " + "%.2f %%"%(result["R100"])
            R80       = ": " + "%.2f %%"%(result["R80"])
            R50       = ": " + "%.2f %%"%(result["R50"])
            E0        = ": " + "%.2f %%"%(result["E0"])
            RP        = ": " + "%.2f"%(result["RP"])
            orderItems   = [[x,y] for x,y in zip(result["x"],result["y"])]
            cursor.insertText("%-8s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("射束类型",rayType,"R100",R100,"打印时间",_time),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("能量",power,"R80",R80,"测量日期",time_pre),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-9s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("源皮距",ssd,"R50",R50,"设备名称",name),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("方向",direction,"E0",E0,"设备房间",room),textFormat)
            cursor.insertBlock()
            cursor.insertText("%-10s%-8s\t%-6s\t%-10s\t%-4s\t%-8s"%("深度",deepth,"RP",RP,'',''),textFormat)

        cursor.setPosition(topFrame.lastPosition())
        cursor.insertBlock()

        bodyFrameFormat = QTextFrameFormat()
        bodyFrameFormat.setWidth(QTextLength(QTextLength.PercentageLength, 100))
        cursor.insertFrame(bodyFrameFormat)

        # 数据总数
        _len = len(orderItems)
        # 显示行数
        num = 21
        # 显示列数
        col = _len//num + 1
        # 列数中包含多少列
        col_col = 2
        orderTableFormat = QTextTableFormat()
        orderTableFormat.setAlignment(Qt.AlignLeft)
        orderTable = cursor.insertTable(1, col*col_col, orderTableFormat)

        orderFrameFormat = cursor.currentFrame().frameFormat()
        orderFrameFormat.setBorder(1)
        cursor.currentFrame().setFrameFormat(orderFrameFormat)

        # 创建表格头显示
        for i in range(col):
            cursor = orderTable.cellAt(0, i*col_col+0).firstCursorPosition()
            cursor.insertText("D(mm)", boldFormat)
            cursor = orderTable.cellAt(0, i*col_col+1).firstCursorPosition()
            cursor.insertText("Q(%)", boldFormat)
        # 插入数据
        for j in range(num):
            row = orderTable.rows()
            orderTable.insertRows(row, 1)
            item = orderItems[j]
            for c in range(col_col):
                cursor = orderTable.cellAt(row, c).firstCursorPosition()
                cursor.insertText(str(item[c]), textFormat)
            for i in range(1, col):
                if (i*num+j) < _len:
                    item = orderItems[i*num+j]
                    for c in range(col_col):
                        cursor = orderTable.cellAt(row, i*col_col+c).firstCursorPosition()
                        cursor.insertText(str(item[c]), textFormat)
        cursor.setPosition(topFrame.lastPosition())
        cursor.insertBlock()

        srcPath = os.getcwd() + '\\temp.png'
        savePath = os.getcwd() + '\\temp_small.png'
        if self.current_print['config']['type'] == "PDD":
            pm = self.chart_pdd.grab();
        if self.current_print['config']['type'] == "OAR":
            pm = self.chart_x.grab();
        if self.current_print['config']['type'] == "EBEAM":
            pm = self.chart_pdd.grab();
        pm.save(srcPath)
        img = Image.open(srcPath)
        w, h = img.size
        img.resize((int(w*2/3), int(h*2/3)),Image.ANTIALIAS).save(savePath, "png")

        fragment = QTextDocumentFragment()
        fragment = QTextDocumentFragment.fromHtml("<img src='%s'>"%savePath)
        cursor.insertFragment(fragment)

        document.print(printer)

    def handleExportExcel(self):
        print(self.current_print)
        conf = self.current_print['config']
        _time     = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        time_pre  = str(conf["time"])
        Type   = str(conf["type"])
        rayType   = str(conf["rayType"])
        raySizeX   = str(conf["raySizeX"])
        raySizeY   = str(conf["raySizeY"])
        power     = str(conf["power"])
        ssd       = str(conf["ssd"])
        direction = str(conf["direction"])
        deepth    = str(conf["deepth"])
        name      = str(conf["name"])
        room      = str(conf["room"])
        result    = self.current_print['result']
        name_time     = time.strftime("%Y%m%d%H%M%S", time.localtime())
        f = QFileDialog.getSaveFileName(self,
                                        "导出Excel",
                                        '%s/data/%s'%(os.getcwd(),name_time+'_'+name+'_'+room+'_'+Type+'_'+rayType+'_'+power+'_'+direction.replace('->','')+'_'+raySizeX+'x'+raySizeY),'Excel Files(*.xls)')
        if f[0]:
            # try:
                filename = f[0]
                # wb = xlwt.Workbook()
                # ws = wb.add_sheet('sheet1')#sheetname
                wb = xlsxwriter.Workbook(filename)
                ws = wb.add_worksheet()
                if conf['type'] == "PDD":
                    if conf['rayType'] == '光子':
                        ws.write(0, 3, "PDD测量数据结果")
                        ws.write(1, 1, "D(mm)")
                        ws.write(1, 2, "Q(%)")
                        data = [[x,y] for x,y in zip(result["x"],result["y"])]
                        for i in range(0,len(data)):
                            ws.write(i+2,1,str(data[i][0]))
                            ws.write(i+2,2,str(data[i][1]))

                        ws.write(1,4,"D0")
                        ws.write(2,4,"D10")
                        ws.write(3,4,"D20")
                        ws.write(4,4,"D20_D10")
                        ws.write(5,4,"R100")
                        ws.write(6,4,"R80")
                        ws.write(7,4,"R50")
                        ws.write(8,4,"Energy")

                        ws.write(1,5,"%.2f %%"%(result["D0"]))
                        ws.write(2,5,"%.2f %%"%(result["D10"]))
                        ws.write(3,5,"%.2f %%"%(result["D20"]))
                        ws.write(4,5,"%.2f   "%(result["D20_D10"]))
                        ws.write(5,5,"%.2f   "%(result["R100"]))
                        ws.write(6,5,"%.2f mm"%(result["R80"]))
                        ws.write(7,5,"%.2f mm"%(result["R50"]))
                        ws.write(8,5,"%.2f MeV"%(result["energy"]))

                        ws.write(1,7,"射束类型")
                        ws.write(2,7,"能量")
                        ws.write(3,7,"源皮距")
                        ws.write(4,7,"方向")
                        ws.write(5,7,"深度")

                        ws.write(1,8,rayType)
                        ws.write(2,8,power)
                        ws.write(3,8,ssd)
                        ws.write(4,8,direction)
                        ws.write(5,8,deepth)

                        ws.write(1,10,"打印时间")
                        ws.write(2,10,"测量日期")
                        ws.write(3,10,"设备名称")
                        ws.write(4,10,"房间名称")

                        ws.write(1,11,_time)
                        ws.write(2,11,time_pre)
                        ws.write(3,11,name)
                        ws.write(4,11,room)

                        savePath= r'%s\data\temp.png'%os.getcwd()
                        pm = self.chart_pdd.grab();
                        pm.save(savePath)
                        ws.insert_image("E12",savePath)
                    if conf['rayType'] == '电子':
                        ws.write(0, 3, "EBEAM测量数据结果")
                        ws.write(1, 1, "D(mm)")
                        ws.write(1, 2, "Q(%)")
                        data = [[x,y] for x,y in zip(result["x"],result["y"])]
                        for i in range(0,len(data)):
                            ws.write(i+2,1,str(data[i][0]))
                            ws.write(i+2,2,str(data[i][1]))

                        ws.write(1,3,"R100")
                        ws.write(2,3,"R80")
                        ws.write(3,3,"R50")
                        ws.write(4,3,"E0")
                        ws.write(5,3,"RP")
                        ws.write(1,4,"%.2f %%"%(result["R100"]))
                        ws.write(2,4,"%.2f %%"%(result["R80"]))
                        ws.write(3,4,"%.2f %%"%(result["R50"]))
                        ws.write(4,4,"%.2f %%"%(result["E0"]))
                        ws.write(5,4,"%.2f"%(result["RP"]))

                        ws.write(1,7,"射束类型")
                        ws.write(2,7,"能量")
                        ws.write(3,7,"源皮距")
                        ws.write(4,7,"方向")
                        ws.write(5,7,"深度")

                        ws.write(1,8,rayType)
                        ws.write(2,8,power)
                        ws.write(3,8,ssd)
                        ws.write(4,8,direction)
                        ws.write(5,8,deepth)

                        ws.write(1,10,"打印时间")
                        ws.write(2,10,"测量日期")
                        ws.write(3,10,"设备名称")
                        ws.write(4,10,"房间名称")

                        ws.write(1,11,_time)
                        ws.write(2,11,time_pre)
                        ws.write(3,11,name)
                        ws.write(4,11,room)

                        savePath= r'%s\data\temp.png'%os.getcwd()
                        pm = self.chart_pdd.grab();
                        pm.save(savePath)
                        ws.insert_image("E12",savePath)

                if conf['type'] == "OAR":
                    if conf['rayType'] == '光子':
                        ws.write(0, 3, "OAR测量数据结果")
                        ws.write(1, 1, "D(mm)")
                        ws.write(1, 2, "Q(%)")
                        data = [[x,y] for x,y in zip(result["x"],result["y"])]
                        for i in range(0,len(data)):
                            ws.write(i+2,1,str(data[i][0]))
                            ws.write(i+2,2,str(data[i][1]))

                        ws.write(1,4,"光野重合性")
                        ws.write(2,4,"均整度")
                        ws.write(3,4,"对称性")
                        ws.write(4,4,"最小剂量率")
                        ws.write(5,4,"左半影")
                        ws.write(6,4,"右半影")
                        ws.write(1,5,"%.1f %%"%(result["Dev"]))
                        ws.write(2,5,"%.2f %%"%(result["flatValue"]))
                        ws.write(3,5,"%.2f %%"%(result["sym"]))
                        ws.write(4,5,"%.2f %%"%(result["Dmin"]))
                        ws.write(5,5,"%.2f"%(result["left_shadow"]))
                        ws.write(6,5,"%.2f"%(result["right_shadow"]))

                        ws.write(1,7,"射束类型")
                        ws.write(2,7,"能量")
                        ws.write(3,7,"源皮距")
                        ws.write(4,7,"方向")
                        ws.write(5,7,"深度")

                        ws.write(1,8,rayType)
                        ws.write(2,8,power)
                        ws.write(3,8,ssd)
                        ws.write(4,8,direction)
                        ws.write(5,8,deepth)

                        ws.write(1,10,"打印时间")
                        ws.write(2,10,"测量日期")
                        ws.write(3,10,"设备名称")
                        ws.write(4,10,"房间名称")

                        ws.write(1,11,_time)
                        ws.write(2,11,time_pre)
                        ws.write(3,11,name)
                        ws.write(4,11,room)

                        savePath= r'%s\data\temp.png'%os.getcwd()
                        if direction == "A->B" or direction == "B->A":
                            pm = self.chart_x.grab();
                        elif direction == "G->T" or direction == "T->G":
                            pm = self.chart_y.grab();
                        pm.save(savePath)
                        ws.insert_image("E12",savePath)
                    if conf['rayType'] == '电子':
                        ws.write(0, 3, "OAR测量数据结果")
                        ws.write(1, 1, "D(mm)")
                        ws.write(1, 2, "Q(%)")
                        data = [[x,y] for x,y in zip(result["x"],result["y"])]
                        for i in range(0,len(data)):
                            ws.write(i+2,1,str(data[i][0]))
                            ws.write(i+2,2,str(data[i][1]))

                        ws.write(2,4,"均整度")
                        ws.write(3,4,"对称性")
                        ws.write(1,5,"%.1f mm"%(result["uniform"]))
                        ws.write(2,5,"%.2f %%"%(result["symmetry"]))

                        ws.write(1,7,"射束类型")
                        ws.write(2,7,"能量")
                        ws.write(3,7,"源皮距")
                        ws.write(4,7,"方向")
                        ws.write(5,7,"深度")

                        ws.write(1,8,rayType)
                        ws.write(2,8,power)
                        ws.write(3,8,ssd)
                        ws.write(4,8,direction)
                        ws.write(5,8,deepth)

                        ws.write(1,10,"打印时间")
                        ws.write(2,10,"测量日期")
                        ws.write(3,10,"设备名称")
                        ws.write(4,10,"房间名称")

                        ws.write(1,11,_time)
                        ws.write(2,11,time_pre)
                        ws.write(3,11,name)
                        ws.write(4,11,room)

                        savePath= r'%s\data\temp.png'%os.getcwd()
                        if direction == "A->B" or direction == "B->A":
                            pm = self.chart_x.grab();
                        elif direction == "G->T" or direction == "T->G":
                            pm = self.chart_y.grab();
                        pm.save(savePath)
                        ws.insert_image("E12",savePath)

                wb.close()

                QMessageBox.warning(self,'提示','导出成功!\r\n%s'%filename,QMessageBox.Yes)

                # if conf['type'] == "OAR":
                    # ws.write(0, 3, "OAR测量数据结果")
                # if conf['type'] == "EBEAM":
                    # ws.write(0, 3, "EBEAM测量数据结果")
                # for i in range(0,len(data)):
                    # for j in range(0,len(data[i])):
                        # ws.write(i, j, data[i][j])
                # wb.save(filename)
            # except:
                # QMessageBox.warning(self,'警告','文件被占用，无法导出!',QMessageBox.Yes)


    def handlePaintRequest_bk(self, printer):
        document = QTextDocument()
        cursor = QTextCursor(document)
        cursor.insertText("打印测试")
        document.print(printer)

    def on_printAction1_triggered(self):
        "动作一：打印，无预览"
        if not self.current_print:
            QMessageBox.warning(self,'警告','请选择要打印的数据!',QMessageBox.Yes)
            return
        printer = QPrinter()
        printDialog = QPrintDialog(printer, self)
        if printDialog.exec_() == QDialog.Accepted:
            self.handlePaintRequest(printer)

    def on_printAction2_triggered(self):
        "动作二：打印，有预览"
        if not self.current_print:
            QMessageBox.warning(self,'警告','请选择要打印的数据!',QMessageBox.Yes)
            return
        dialog = QPrintPreviewDialog()
        w = QApplication.desktop().screenGeometry().width()
        h = QApplication.desktop().screenGeometry().height()
        dialog.setFixedSize(w/2,h*3/4)
        dialog.paintRequested.connect(self.handlePaintRequest)
        dialog.exec_()

    # def keyPressEvent(self, event):
        # if (event.key() == Qt.Key_Delete):
            # self.TaskTree.deleteSelected()
            # pass

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    #  window = TreeWidgetTask()
    window = chartAnalyseForm()
    window.show()
    window.resize(1266, 768)
    app.exec_()

